*/
/*
-This version is for pigpio version 34+
+This version is for pigpio version 35+
*/
#include <stdio.h>
{PI_BAD_I2C_RLEN , "bad I2C read length"},
{PI_BAD_I2C_CMD , "bad I2C command"},
{PI_BAD_I2C_BAUD , "bad I2C baud rate, not 50-500k"},
- {PI_BAD_REPEAT_CNT , "bad repeat count, not 2-max"},
- {PI_BAD_REPEAT_WID , "bad repeat wave id"},
- {PI_TOO_MANY_COUNTS , "too many chain counters"},
- {PI_BAD_CHAIN_CMD , "malformed chain command string"},
- {PI_REUSED_WID , "wave already used in chain"},
+ {PI_CHAIN_LOOP_CNT , "bad chain loop count"},
+ {PI_BAD_CHAIN_LOOP , "empty chain loop"},
+ {PI_CHAIN_COUNTER , "too many chain counters"},
+ {PI_BAD_CHAIN_CMD , "bad chain command"},
+ {PI_BAD_CHAIN_DELAY , "bad chain delay micros"},
+ {PI_CHAIN_NESTING , "chain counters nested too deeply"},
+ {PI_CHAIN_TOO_BIG , "chain is too long"},
+ {PI_DEPRECATED , "deprecated function removed"},
};
char c;
uint32_t tp1, tp2, tp3;
int8_t to1, to2, to3;
+ int eaten;
/* Check that ext is big enough for the largest message. */
if (ext_len < (4 * CMD_MAX_PARAM)) return CMD_EXT_TOO_SMALL;
while (pars < CMD_MAX_PARAM)
{
- ctl->eaten += getNum(buf+ctl->eaten, &tp1, &to1);
- if ((to1 == CMD_NUMERIC) &&
- ((int)tp1>=0) && ((int)tp1<=255))
+ eaten = getNum(buf+ctl->eaten, &tp1, &to1);
+ if (to1 == CMD_NUMERIC)
{
- pars++;
- *p8++ = tp1;
+ if (((int)tp1>=0) && ((int)tp1<=255))
+ {
+ pars++;
+ *p8++ = tp1;
+ ctl->eaten += eaten;
+ }
+ else break; /* invalid number, end of command */
}
else break;
}
while (pars < 32)
{
- ctl->eaten += getNum(buf+ctl->eaten, &tp1, &to1);
- if ((to1 == CMD_NUMERIC) &&
- ((int)tp1>=0) &&
- ((int)tp1<=255))
+ eaten = getNum(buf+ctl->eaten, &tp1, &to1);
+ if (to1 == CMD_NUMERIC)
{
- pars++;
- *p8++ = tp1;
+ if (((int)tp1>=0) && ((int)tp1<=255))
+ {
+ pars++;
+ *p8++ = tp1;
+ ctl->eaten += eaten;
+ }
+ else break; /* invalid number, end of command */
}
else break;
}
while (pars < CMD_MAX_PARAM)
{
- ctl->eaten += getNum(buf+ctl->eaten, &tp1, &to1);
+ eaten = getNum(buf+ctl->eaten, &tp1, &to1);
if (to1 == CMD_NUMERIC)
{
if (((int)tp1>=0) && ((int)tp1<=255))
{
pars++;
*p8++ = tp1;
+ ctl->eaten += eaten;
}
- else valid = 0;
+ else break;
}
else break;
}
p8 = ext + 12;
while (pars < CMD_MAX_PARAM)
{
- ctl->eaten += getNum(buf+ctl->eaten, &tp1, &to1);
- if ((to1 == CMD_NUMERIC) &&
- ((int)tp1>=0) && ((int)tp1<=255))
+ eaten = getNum(buf+ctl->eaten, &tp1, &to1);
+ if (to1 == CMD_NUMERIC)
{
- *p8++ = tp1;
- pars++;
+ if (((int)tp1>=0) && ((int)tp1<=255))
+ {
+ *p8++ = tp1;
+ pars++;
+ ctl->eaten += eaten;
+ }
+ else break; /* invalid number, end of command */
}
else break;
}
while (pars < CMD_MAX_PARAM)
{
- ctl->eaten += getNum(buf+ctl->eaten, &tp1, &to1);
- if ((to1 == CMD_NUMERIC) &&
- ((int)tp1>=0) && ((int)tp1<=255))
+ eaten = getNum(buf+ctl->eaten, &tp1, &to1);
+ if (to1 == CMD_NUMERIC)
{
- pars++;
- *p8++ = tp1;
+ if (((int)tp1>=0) && ((int)tp1<=255))
+ {
+ pars++;
+ *p8++ = tp1;
+ ctl->eaten += eaten;
+ }
+ else break; /* invalid number, end of command */
}
else break;
}
.IP "\fBint gpioWaveCreate(void)\fP"
.IP "" 4
This function creates a waveform from the data provided by the prior
-calls to the \fBgpioWaveAdd*\fP functions. Upon success a positive wave id
-is returned.
+calls to the \fBgpioWaveAdd*\fP functions. Upon success a wave id
+greater than or equal to 0 is returned, otherwise PI_EMPTY_WAVEFORM,
+PI_TOO_MANY_CBS, PI_TOO_MANY_OOL, or PI_NO_WAVEFORM_ID.
.br
.IP "\fBint gpioWaveDelete(unsigned wave_id)\fP"
.IP "" 4
-This function deletes all created waveforms with ids greater than or
-equal to wave_id.
+This function deletes the waveform with id wave_id.
.br
.br
Returns 0 if OK, otherwise PI_BAD_WAVE_ID.
-.IP "\fBint gpioWaveTxStart(unsigned wave_mode)\fP"
-.IP "" 4
-This function creates and then transmits a waveform. The mode
-determines whether the waveform is sent once or cycles endlessly.
-
-.br
-
-.br
-NOTE: Any hardware PWM started by \fBgpioHardwarePWM\fP will be cancelled.
-
-.br
-
-.br
-
-.EX
-wave_mode: 0 (PI_WAVE_MODE_ONE_SHOT), 1 (PI_WAVE_MODE_REPEAT)
-.br
-
-.EE
-
-.br
-
-.br
-This function is deprecated and should no longer be used. Use
-\fBgpioWaveCreate\fP and \fBgpioWaveTxSend\fP instead.
-
-.br
-
-.br
-Returns the number of DMA control blocks in the waveform if OK,
-otherwise PI_BAD_WAVE_MODE.
-
.IP "\fBint gpioWaveTxSend(unsigned wave_id, unsigned wave_mode)\fP"
.IP "" 4
This function transmits the waveform with id wave_id. The mode
.br
The waves to be transmitted are specified by the contents of buf
-which contains an ordered list of wave_ids and optional command
+which contains an ordered list of \fBwave_id\fPs and optional command
codes and related data.
.br
.br
.br
-Returns 0 if OK, otherwise PI_BAD_REPEAT_CNT, PI_BAD_REPEAT_WID,
-PI_BAD_CHAIN_CMD, PI_TOO_MANY_COUNTS, or PI_BAD_WAVE_ID.
+Returns 0 if OK, otherwise PI_CHAIN_NESTING, PI_CHAIN_LOOP_CNT, PI_BAD_CHAIN_LOOP, PI_BAD_CHAIN_CMD, PI_CHAIN_COUNTER,
+PI_BAD_CHAIN_DELAY, PI_CHAIN_TOO_BIG, or PI_BAD_WAVE_ID.
.br
.br
-Each wave is transmitted in the order specified. A wave may only
-occur once per chain. Waves may be transmitted multiple times by
-using the repeat command. The repeat command specifies a wave id
-and a count. The wave id must occur earlier in the chain. All the
-waves between wave id and the repeat command are transmitted count
-times.
+Each wave is transmitted in the order specified. A wave may
+occur multiple times per chain.
.br
.br
-Repeat commands may not be nested. The minimum repeat count is 2.
-A maximum of 5 repeat commands is supported per chain.
+A blocks of waves may be transmitted multiple times by using
+the loop commands. The block is bracketed by loop start and
+end commands. Loops may be nested.
+
+.br
+
+.br
+Delays between waves may be added with the delay command.
.br
.br
.br
-Name Cmd & Data Meaning
+Name Cmd & Data Meaning
.br
-Repeat 255 wid C0 C1 C2 Repeat from wid count times
+Loop Start 255 0 Identify start of a wave block
.br
-count = C0 + C1*256 + C2*65536
+Loop Repeat 255 1 x y loop x + y*256 times
+
+.br
+Delay 255 2 x y delay x + y*256 microseconds
+
+.br
+
+.br
+
+.br
+The code is currently dimensioned to support a chain with roughly
+600 entries and 20 loop counters.
.br
.br
.EX
-The following examples assume that waves with ids 0 to 12 exist.
+#include <stdio.h>
+.br
+#include <pigpio.h>
.br
.br
-// 0 255 0 57 0 0 (repeat 0 57 times)
+#define WAVES 5
.br
-status = gpioWaveChain((char []){0, 255, 0, 57, 0, 0}, 6);
+#define GPIO 4
.br
.br
-// 0 1 255 0 0 2 0 (repeat 0+1 512 times)
+int main(int argc, char *argv[])
+.br
+{
.br
-status = gpioWaveChain((char []){0, 1, 255, 0, 0, 2, 0}, 7);
+ int i, wid[WAVES];
.br
.br
-// 0 1 255 1 0 0 1 (transmit 0, repeat 1 65536 times)
+ if (gpioInitialise()<0) return -1;
.br
-status = gpioWaveChain((char []){0, 1, 255, 1, 0, 0, 1}, 7);
+
+.br
+ gpioSetMode(GPIO, PI_OUTPUT);
.br
.br
-// 0 1 2 3 255 2 13 0 0 (transmit 0+1, repeat 2+3 13 times)
+ printf("start piscope, press return\n"); getchar();
+.br
+
+.br
+ for (i=0; i<WAVES; i++)
+.br
+ {
+.br
+ gpioWaveAddGeneric(2, (gpioPulse_t[])
.br
-status = gpioWaveChain(
+ {{1<<GPIO, 0, 20},
.br
- (char []){0, 1, 2, 3, 255, 2, 13, 0, 0}, 9);
+ {0, 1<<GPIO, (i+1)*200}});
.br
.br
-// The following repeats 5 65793 times, transmits 6,
+ wid[i] = gpioWaveCreate();
+.br
+ }
+.br
+
+.br
+ gpioWaveChain((char []) {
+.br
+ wid[4], wid[3], wid[2], // transmit waves 4+3+2
+.br
+ 255, 0, // loop start
+.br
+ wid[0], wid[0], wid[0], // transmit waves 0+0+0
+.br
+ 255, 0, // loop start
+.br
+ wid[0], wid[1], // transmit waves 0+1
.br
-// repeats 7+8 514 times, transmits 12,
+ 255, 2, 0x88, 0x13, // delay 5000us
.br
-// repeats 9+11+10 197121 times.
+ 255, 1, 30, 0, // loop end (repeat 30 times)
.br
-// 5 255 5 1 1 1 6 7 8 255 7 2 2 0 12 9 11 10 255 9 1 2 3
+ 255, 0, // loop start
.br
-char chain[] = {
+ wid[2], wid[3], wid[0], // transmit waves 2+3+0
.br
- 5, 255, 5, 1, 1, 1,
+ wid[3], wid[1], wid[2], // transmit waves 3+1+2
.br
- 6, 7, 8, 255, 7, 2, 2, 0,
+ 255, 1, 10, 0, // loop end (repeat 10 times)
.br
- 12, 9, 11, 10, 255, 9, 1, 2, 3};
+ 255, 1, 5, 0, // loop end (repeat 5 times)
+.br
+ wid[4], wid[4], wid[4], // transmit waves 4+4+4
+.br
+ 255, 2, 0x20, 0x4E, // delay 20000us
+.br
+ wid[0], wid[0], wid[0], // transmit waves 0+0+0
+.br
+
+.br
+ }, 46);
.br
.br
-status = gpioWaveChain(chain, sizeof(chain));
+ while (gpioWaveTxBusy()) time_sleep(0.1);
+.br
+
+.br
+ for (i=0; i<WAVES; i++) gpioWaveDelete(wid[i]);
+.br
+
+.br
+ printf("stop piscope, press return\n"); getchar();
+.br
+
+.br
+ gpioTerminate();
+.br
+}
.br
.EE
.br
.br
-NOTE: Any waveform started by \fBgpioWaveTxSend\fP, \fBgpioWaveTxStart\fP,
-or \fBgpioWaveChain\fP will be cancelled.
+NOTE: Any waveform started by \fBgpioWaveTxSend\fP, or
+\fBgpioWaveChain\fP will be cancelled.
.br
.br
.br
-A number representing a waveform created by \fBgpioWaveCreate\fP.
+A number identifying a waveform created by \fBgpioWaveCreate\fP.
.br
.br
#define PI_BAD_I2C_BAUD -112 // bad I2C baud rate, not 50-500k
.br
-#define PI_BAD_REPEAT_CNT -113 // bad repeat count, not 2-max
+#define PI_CHAIN_LOOP_CNT -113 // bad chain loop count
+.br
+#define PI_BAD_CHAIN_LOOP -114 // empty chain loop
+.br
+#define PI_CHAIN_COUNTER -115 // too many chain counters
+.br
+#define PI_BAD_CHAIN_CMD -116 // bad chain command
.br
-#define PI_BAD_REPEAT_WID -114 // bad repeat wave id
+#define PI_BAD_CHAIN_DELAY -117 // bad chain delay micros
.br
-#define PI_TOO_MANY_COUNTS -115 // too many chain counters
+#define PI_CHAIN_NESTING -118 // chain counters nested too deeply
.br
-#define PI_BAD_CHAIN_CMD -116 // malformed chain command string
+#define PI_CHAIN_TOO_BIG -119 // chain is too long
.br
-#define PI_REUSED_WID -117 // wave already used in chain
+#define PI_DEPRECATED -120 // deprecated function removed
.br
.br
For more information, please refer to <http://unlicense.org/>
*/
-/* pigpio version 34 */
+/* pigpio version 35 */
/* include ------------------------------------------------------- */
#define NORMAL_DMA (DMA_NO_WIDE_BURSTS | DMA_WAIT_RESP)
-#define TIMED_DMA(x) (DMA_DEST_DREQ | DMA_PERIPHERAL_MAPPING(x))
+#define TIMED_DMA(x) (DMA_DEST_DREQ | DMA_PERIPHERAL_MAPPING(x))
+
+#define PCM_TIMER (((PCM_BASE + PCM_FIFO*4) & 0x00ffffff) | PI_PERI_BUS)
+#define PWM_TIMER (((PWM_BASE + PWM_FIFO*4) & 0x00ffffff) | PI_PERI_BUS)
#define DBG_MIN_LEVEL 0
#define DBG_ALWAYS 0
#define CBS_PER_OPAGE 118
#define OOL_PER_OPAGE 79
+/*
+Wave Count Block
+
+Assumes two counters per block. Each counter 4 * 16 (16^4=65536)
+ 0 CB [13] 13*8 104 CBs for counter 0
+ 104 CB [13] 13*8 104 CBs for counter 1
+ 208 CB [60] 60*8 480 CBs reserved to construct wave
+ 688 OOL [60] 60*1 60 OOL reserved to construct wave
+ 748 OOL[136] 136*1 136 OOL for counter 0
+ 884 OOL[136] 136*1 136 OOL for counter 1
+1020 pad [4] 4*1 4 spare
+*/
+
+#define WCB_CNT_PER_PAGE 2
+#define WCB_COUNTERS (WCB_CNT_PER_PAGE * PI_WAVE_COUNT_PAGES)
+#define WCB_CNT_CBS 13
+#define WCB_CNT_OOL 68
+#define WCB_COUNTER_OOL (WCB_CNT_PER_PAGE * WCB_CNT_OOL)
+#define WCB_COUNTER_CBS (WCB_CNT_PER_PAGE * WCB_CNT_CBS)
+#define WCB_CHAIN_CBS 60
+#define WCB_CHAIN_OOL 60
+
#define CBS_PER_CYCLE ((PULSE_PER_CYCLE*3)+2)
#define NUM_CBS (CBS_PER_CYCLE * bufferCycles)
static wfRx_t wfRx[PI_MAX_USER_GPIO+1];
-static int waveOutBotCB = PI_WAVE_COUNTERS*CBS_PER_OPAGE;
-static int waveOutTopCB = NUM_WAVE_CBS;
-static int waveOutBotOOL = PI_WAVE_COUNTERS*OOL_PER_OPAGE;
+static int waveOutBotCB = PI_WAVE_COUNT_PAGES*CBS_PER_OPAGE;
+static int waveOutBotOOL = PI_WAVE_COUNT_PAGES*OOL_PER_OPAGE;
static int waveOutTopOOL = NUM_WAVE_OOL;
static int waveOutCount = 0;
static void initDMAgo(volatile uint32_t *dmaAddr, uint32_t cbAddr);
+int gpioWaveTxStart(unsigned wave_mode); /* deprecated */
+
+
/* ======================================================================= */
static char * myTimeStamp()
}
-/* ----------------------------------------------------------------------- */
-
-static void waveCbOPrint(int pos)
-{
- rawCbs_t * p;
-
- p = rawWaveCBAdr(pos);
-
- fprintf(stderr, "i=%x s=%x d=%x len=%x s=%x nxt=%x\n",
- p->info, p->src, p->dst, p->length, p->stride, p->next);
-}
-
-
/* ----------------------------------------------------------------------- */
static void waveBitDelay
/* ----------------------------------------------------------------------- */
-static int errCBsOOL(int cb, int botOOL, int topOOL)
+static void waveCBsOOLs(int *numCBs, int *numBOOLs, int *numTOOLs)
{
- if (cb >= waveOutTopCB) return PI_TOO_MANY_CBS;
+ int numCB=0, numBOOL=0, numTOOL=0;
- if (botOOL >= topOOL) return PI_TOO_MANY_OOL;
+ unsigned i;
- return 0;
+ unsigned numWaves;
+
+ rawWave_t *waves;
+
+ numWaves = wfc[wfcur];
+ waves = wf [wfcur];
+
+ /* delay cb at start of DMA */
+
+ numCB++;
+
+ for (i=0; i<numWaves; i++)
+ {
+ if (waves[i].gpioOn) {numCB++; numBOOL++;}
+ if (waves[i].gpioOff) {numCB++; numBOOL++;}
+ if (waves[i].flags & WAVE_FLAG_READ) {numCB++; numTOOL++;}
+ if (waves[i].flags & WAVE_FLAG_TICK) {numCB++; numTOOL++;}
+ if (waves[i].usDelay) {numCB++; }
+ }
+
+ *numCBs = numCB;
+ *numBOOLs = numBOOL;
+ *numTOOLs = numTOOL;
}
/* ----------------------------------------------------------------------- */
-static int wave2Cbs(unsigned wave_mode)
+static int wave2Cbs(unsigned wave_mode, int *CB, int *BOOL, int *TOOL)
{
- int botCB=waveOutBotCB, botOOL=waveOutBotOOL, topOOL=waveOutTopOOL;
+ int botCB=*CB, botOOL=*BOOL, topOOL=*TOOL;
int status;
half = PI_WF_MICROS/2;
- if ((status = errCBsOOL(botCB+1, botOOL, topOOL))) return status;
-
/* add delay cb at start of DMA */
p = rawWaveCBAdr(botCB++);
if (gpioCfg.clockPeriph != PI_CLOCK_PCM)
{
- p->info = NORMAL_DMA |
- DMA_DEST_DREQ |
- DMA_PERIPHERAL_MAPPING(2);
- p->dst = ((PCM_BASE + PCM_FIFO*4) & 0x00ffffff) | PI_PERI_BUS;
+ p->info = NORMAL_DMA | TIMED_DMA(2);
+ p->dst = PCM_TIMER;
}
else
{
- p->info = NORMAL_DMA |
- DMA_DEST_DREQ |
- DMA_PERIPHERAL_MAPPING(5);
- p->dst = ((PWM_BASE + PWM_FIFO*4) & 0x00ffffff) | PI_PERI_BUS;
+ p->info = NORMAL_DMA | TIMED_DMA(5);
+ p->dst = PWM_TIMER;
}
p->src = (uint32_t) (&dmaOBus[0]->periphData);
{
if (waves[i].gpioOn)
{
- if ((status = errCBsOOL(botCB+1, botOOL+1, topOOL))) return status;
-
waveSetOOL(botOOL, waves[i].gpioOn);
p = rawWaveCBAdr(botCB++);
if (waves[i].gpioOff)
{
- if ((status = errCBsOOL(botCB+1, botOOL+1, topOOL))) return status;
-
waveSetOOL(botOOL, waves[i].gpioOff);
p = rawWaveCBAdr(botCB++);
if (waves[i].flags & WAVE_FLAG_READ)
{
- if ((status = errCBsOOL(botCB+1, botOOL, topOOL-1))) return status;
-
p = rawWaveCBAdr(botCB++);
p->info = NORMAL_DMA;
if (waves[i].flags & WAVE_FLAG_TICK)
{
- if ((status = errCBsOOL(botCB+1, botOOL, topOOL-1))) return status;
-
p = rawWaveCBAdr(botCB++);
p->info = NORMAL_DMA;
if (waves[i].usDelay)
{
- if ((status = errCBsOOL(botCB+1, botOOL, topOOL))) return status;
-
p = rawWaveCBAdr(botCB++);
/* use the secondary clock */
if (gpioCfg.clockPeriph != PI_CLOCK_PCM)
{
- p->info = NORMAL_DMA |
- DMA_DEST_DREQ |
- DMA_PERIPHERAL_MAPPING(2);
-
- p->dst = ((PCM_BASE + PCM_FIFO*4) & 0x00ffffff) | PI_PERI_BUS;
+ p->info = NORMAL_DMA | TIMED_DMA(2);
+ p->dst = PCM_TIMER;
}
else
{
- p->info = NORMAL_DMA |
- DMA_DEST_DREQ |
- DMA_PERIPHERAL_MAPPING(5);
-
- p->dst = ((PWM_BASE + PWM_FIFO*4) & 0x00ffffff) | PI_PERI_BUS;
+ p->info = NORMAL_DMA | TIMED_DMA(5);
+ p->dst = PWM_TIMER;
}
p->src = (uint32_t) (&dmaOBus[0]->periphData);
else p->next = waveCbPOadr(repeatCB);
}
- status = botCB - waveOutBotCB;
+ status = botCB - *CB;
- waveOutBotCB = botCB;
- waveOutBotOOL = botOOL;
- waveOutTopOOL = topOOL;
+ *CB = botCB;
+ *BOOL = botOOL;
+ *TOOL = topOOL;
return status;
}
-/* ----------------------------------------------------------------------- */
-
-static uint32_t waveGetIn(int page, int slot)
-{
- return (dmaOVirt[page]->OOL[slot]);
-}
-
-static void waveSetIn(int page, int slot, uint32_t value)
-{
- dmaOVirt[page]->OOL[slot] = value;
-}
-
-static uint32_t myWaveOOLPOadr(int page, int slot)
-{
- return (uint32_t) &dmaOBus[page]->OOL[slot];
-}
-
-static void waveCount(
- unsigned counter,
- unsigned blklen,
- unsigned blocks,
- unsigned count,
- uint32_t repeat,
- uint32_t next)
-{
- rawCbs_t *p=NULL;
-
- int b, baseCB, dig;
- uint32_t nxt;
-
- int botCB;
-
- botCB = counter * CBS_PER_OPAGE;
-
- baseCB = botCB;
-
- /* set up all the OOLs */
- for (b=0; b < (blocks*(blklen+1)); b++) waveSetIn(counter, b, repeat);
-
- for (b=0; b<blocks; b++)
- waveSetIn(counter, ((b*(blklen+1))+blklen), waveCbPOadr(baseCB+((b*3)+3)));
-
- for (b=0; b<blocks; b++)
- {
- /* copy BOTTOM to NEXT */
-
- p = rawWaveCBAdr(botCB++);
-
- p->info = NORMAL_DMA;
-
- p->src = myWaveOOLPOadr(counter, b*(blklen+1));
- p->dst = (waveCbPOadr(botCB+1) + 20);
-
- p->length = 4;
- p->next = waveCbPOadr(botCB);
-
- /* copy BOTTOM to TOP */
-
- p = rawWaveCBAdr(botCB++);
-
- p->info = NORMAL_DMA;
-
- p->src = myWaveOOLPOadr(counter, b*(blklen+1));
- p->dst = myWaveOOLPOadr(counter, (b*(blklen+1))+blklen);
-
- p->length = 4;
- p->next = waveCbPOadr(botCB);
-
- /* shift all down one */
-
- p = rawWaveCBAdr(botCB++);
-
- p->info = NORMAL_DMA|DMA_SRC_INC|DMA_DEST_INC;
-
- p->src = myWaveOOLPOadr(counter, ((b*(blklen+1))+1));
- p->dst = myWaveOOLPOadr(counter, ((b*(blklen+1))+0));
-
- p->length = blklen*4;
- p->next = repeat;
- }
-
- b = 0;
-
- while (count && (b<blocks))
- {
- dig = count % blklen;
- count /= blklen;
-
- if (count) nxt = waveGetIn(counter, (b*(blklen+1))+blklen);
- else nxt = next;
-
- waveSetIn(counter, b*(blklen+1)+dig, nxt);
-
- b++;
- }
-}
-
-
/* ----------------------------------------------------------------------- */
static void waveRxSerial(wfRx_t *w, int level, uint32_t tick)
if (gpioCfg.clockPeriph == PI_CLOCK_PCM)
{
- p->info = NORMAL_DMA | TIMED_DMA(2);
- p->dst = ((PCM_BASE + PCM_FIFO*4) & 0x00ffffff) | PI_PERI_BUS;
+ p->info = NORMAL_DMA | TIMED_DMA(2);
+ p->dst = PCM_TIMER;
}
else
{
- p->info = NORMAL_DMA | TIMED_DMA(5);
- p->dst = ((PWM_BASE + PWM_FIFO*4) & 0x00ffffff) | PI_PERI_BUS;
+ p->info = NORMAL_DMA | TIMED_DMA(5);
+ p->dst = PWM_TIMER;
}
p->src = dmaPwmDataAdr(b%DMAI_PAGES);
static void switchFunctionOff(unsigned gpio)
{
- unsigned clock, pwm;
- int cctl[] = {CLK_GP0_CTL, CLK_GP1_CTL, CLK_GP2_CTL};
-
switch (gpioInfo[gpio].is)
{
case GPIO_SERVO:
break;
case GPIO_HW_CLK:
- /* switch hardware clock off */
- clock = (clkDef[gpio] >> 4) & 3;
- clkReg[cctl[clock]] = CLK_PASSWD | CLK_CTL_KILL;
+ /* No longer disable clock hardware, doing that was a bug. */
gpioInfo[gpio].width = 0;
break;
case GPIO_HW_PWM:
- /* switch hardware PWM off */
- pwm = (PWMDef[gpio] >> 4) & 3;
- if (pwm == 0) pwmReg[PWM_CTL] &= (~PWM_CTL_PWEN1);
- else pwmReg[PWM_CTL] &= (~PWM_CTL_PWEN2);
+ /* No longer disable PWM hardware, doing that was a bug. */
gpioInfo[gpio].width = 0;
break;
}
static void stopHardwarePWM(void)
{
- int i;
+ unsigned i, pwm;
for (i=0; i<= PI_MAX_GPIO; i++)
{
if (gpioInfo[i].is == GPIO_HW_PWM)
{
- switchFunctionOff(i);
+ pwm = (PWMDef[i] >> 4) & 3;
+ if (pwm == 0) pwmReg[PWM_CTL] &= (~PWM_CTL_PWEN1);
+ else pwmReg[PWM_CTL] &= (~PWM_CTL_PWEN2);
+
+ gpioInfo[i].width = 0;
gpioInfo[i].is = GPIO_UNDEFINED;
}
}
wfStats.pulses = 0;
wfStats.cbs = 0;
- waveOutBotCB = PI_WAVE_COUNTERS*CBS_PER_OPAGE;
- waveOutTopCB = NUM_WAVE_CBS;
- waveOutBotOOL = PI_WAVE_COUNTERS*OOL_PER_OPAGE;
+ waveOutBotCB = PI_WAVE_COUNT_PAGES*CBS_PER_OPAGE;
+ waveOutBotOOL = PI_WAVE_COUNT_PAGES*OOL_PER_OPAGE;
waveOutTopOOL = NUM_WAVE_OOL;
waveOutCount = 0;
if ((baud < PI_WAVE_MIN_BAUD) || (baud > PI_WAVE_MAX_BAUD))
SOFT_ERROR(PI_BAD_WAVE_BAUD, "bad baud rate (%d)", baud);
- if ((data_bits < PI_MIN_WAVE_DATABITS) || (data_bits > PI_MAX_WAVE_DATABITS))
+ if ((data_bits < PI_MIN_WAVE_DATABITS) ||
+ (data_bits > PI_MAX_WAVE_DATABITS))
SOFT_ERROR(PI_BAD_DATABITS, "bad number of databits (%d)", data_bits);
if ((stop_bits < PI_MIN_WAVE_HALFSTOPBITS) ||
int gpioWaveCreate(void)
{
- int cb;
+ int i, wid;
+ int numCB, numBOOL, numTOOL;
+ int CB, BOOL, TOOL;
DBG(DBG_USER, "");
if (wfc[wfcur] == 0) return PI_EMPTY_WAVEFORM;
- if (waveOutCount < PI_MAX_WAVES)
+ /* What resources are needed? */
+
+ waveCBsOOLs(&numCB, &numBOOL, &numTOOL);
+
+ wid = -1;
+
+ /* Is there an exact fit with a deleted wave. */
+
+ for (i=0; i<waveOutCount; i++)
+ {
+ if (waveInfo[i].deleted &&
+ (waveInfo[i].numCB == numCB) &&
+ (waveInfo[i].numBOOL == numBOOL) &&
+ (waveInfo[i].numTOOL == numTOOL))
+ {
+ /* Reuse the deleted waves resources. */
+ wid = i;
+ break;
+ }
+ }
+
+ if (wid == -1)
{
- waveInfo[waveOutCount].botCB = waveOutBotCB;
- waveInfo[waveOutCount].botOOL = waveOutBotOOL;
- waveInfo[waveOutCount].topOOL = waveOutTopOOL;
+ /* Are there enough spare resources? */
- if ((cb = wave2Cbs(PI_WAVE_MODE_ONE_SHOT)) < 0) return cb;
+ if ((numCB+waveOutBotCB) >= NUM_WAVE_CBS)
+ return PI_TOO_MANY_CBS;
- waveInfo[waveOutCount].topCB = waveOutBotCB-1;
+ if ((numBOOL+waveOutBotOOL) >= (waveOutTopOOL-numTOOL))
+ return PI_TOO_MANY_OOL;
- gpioWaveAddNew();
+ if (wid >= PI_MAX_WAVES)
+ return PI_NO_WAVEFORM_ID;
- return waveOutCount++;
+ wid = waveOutCount++;
+
+ waveInfo[wid].botCB = waveOutBotCB;
+ waveInfo[wid].topCB = waveOutBotCB + numCB -1;
+ waveInfo[wid].botOOL = waveOutBotOOL;
+ waveInfo[wid].topOOL = waveOutTopOOL;
+ waveInfo[wid].numCB = numCB;
+ waveInfo[wid].numBOOL = numBOOL;
+ waveInfo[wid].numTOOL = numTOOL;
+
+ waveOutBotCB += numCB;
+ waveOutBotOOL += numBOOL;
+ waveOutTopOOL -= numTOOL;
}
- return PI_NO_WAVEFORM_ID;
-}
+ /* Must be room if got this far. */
-/* ----------------------------------------------------------------------- */
+ CB = waveInfo[wid].botCB;
+ BOOL = waveInfo[wid].botOOL;
+ TOOL = waveInfo[wid].topOOL;
-int gpioWaveDelete(unsigned wave_id)
-{
- DBG(DBG_USER, "wave id=%d", wave_id);
+ wave2Cbs(PI_WAVE_MODE_ONE_SHOT, &CB, &BOOL, &TOOL);
- CHECK_INITED;
+ /* Sanity check. */
- if (wave_id >= waveOutCount)
- SOFT_ERROR(PI_BAD_WAVE_ID, "bad wave id (%d)", wave_id);
+ if ( (numCB != (CB-waveInfo[wid].botCB)) ||
+ (numBOOL != (BOOL-waveInfo[wid].botOOL)) ||
+ (numTOOL != (waveInfo[wid].topOOL-TOOL)) )
+ {
+ DBG(0, "ERROR wid=%d CBs %d=%d BOOL %d=%d TOOL %d=%d", wid,
+ numCB, CB-waveInfo[wid].botCB,
+ numBOOL, BOOL-waveInfo[wid].botOOL,
+ numTOOL, waveInfo[wid].topOOL-TOOL);
+ }
- waveOutBotCB = waveInfo[wave_id].botCB;
- waveOutBotOOL = waveInfo[wave_id].botOOL;
- waveOutTopOOL = waveInfo[wave_id].topOOL;
+ waveInfo[wid].deleted = 0;
- waveOutCount = wave_id;
+ /* Consume waves. */
- return 0;
+ wfc[0] = 0;
+ wfc[1] = 0;
+ wfc[2] = 0;
+
+ wfcur = 0;
+
+ return wid;
}
/* ----------------------------------------------------------------------- */
-int gpioWaveTxStart(unsigned wave_mode)
+int gpioWaveDelete(unsigned wave_id)
{
- /* This function is deprecated and will be removed. */
-
- int firstCB=PI_WAVE_COUNTERS*CBS_PER_OPAGE;
- int numCBs, i;
-
- DBG(DBG_USER, "wave_mode=%d", wave_mode);
+ DBG(DBG_USER, "wave id=%d", wave_id);
CHECK_INITED;
- if (wave_mode > PI_WAVE_MODE_REPEAT)
- SOFT_ERROR(PI_BAD_WAVE_MODE, "bad wave mode (%d)", wave_mode);
+ if ((wave_id >= waveOutCount) || waveInfo[wave_id].deleted)
+ SOFT_ERROR(PI_BAD_WAVE_ID, "bad wave id (%d)", wave_id);
- if (wfc[wfcur] == 0) return 0;
+ waveInfo[wave_id].deleted = 1;
- if (!waveClockInited)
+ if (wave_id == (waveOutCount-1))
{
- stopHardwarePWM();
- initClock(0); /* initialise secondary clock */
- waveClockInited = 1;
- }
+ /* top wave deleted, garbage collect any other deleted waves */
- dmaOut[DMA_CS] = DMA_CHANNEL_RESET;
+ while ((wave_id > 0) && (waveInfo[wave_id-1].deleted)) --wave_id;
- dmaOut[DMA_CONBLK_AD] = 0;
+ waveOutBotCB = waveInfo[wave_id].botCB;
+ waveOutBotOOL = waveInfo[wave_id].botOOL;
+ waveOutTopOOL = waveInfo[wave_id].topOOL;
- waveOutBotCB = firstCB;
- waveOutTopCB = NUM_WAVE_CBS;
- waveOutBotOOL = PI_WAVE_COUNTERS*OOL_PER_OPAGE;
- waveOutTopOOL = NUM_WAVE_OOL;
-
- waveOutCount = 0;
+ waveOutCount = wave_id;
+ }
- numCBs = wave2Cbs(wave_mode);
+ return 0;
+}
- if (numCBs > 0)
- {
- if (gpioCfg.dbgLevel >= DBG_SLOW_TICK)
- {
- fprintf(stderr, "*** OUTPUT DMA CONTROL BLOCKS ***\n");
- for (i=0; i<numCBs; i++) waveCbOPrint(firstCB+i);
- }
+/* ----------------------------------------------------------------------- */
- initDMAgo((uint32_t *)dmaOut, waveCbPOadr(firstCB));
- }
+int gpioWaveTxStart(unsigned wave_mode)
+{
+ /* This function is deprecated and has been removed. */
- return numCBs;
+ CHECK_INITED;
+ SOFT_ERROR(PI_DEPRECATED, "deprected function removed");
}
/* ----------------------------------------------------------------------- */
CHECK_INITED;
- if (wave_id >= waveOutCount)
+ if ((wave_id >= waveOutCount) || waveInfo[wave_id].deleted)
SOFT_ERROR(PI_BAD_WAVE_ID, "bad wave id (%d)", wave_id);
if (wave_mode > PI_WAVE_MODE_REPEAT)
return (waveInfo[wave_id].topCB - waveInfo[wave_id].botCB) + 1;
}
+
/* ----------------------------------------------------------------------- */
+static int chainGetCB(int n)
+{
+ int block, index;
+
+ if (n < (WCB_CHAIN_CBS * PI_WAVE_COUNT_PAGES))
+ {
+ block = n / WCB_CHAIN_CBS;
+ index = n % WCB_CHAIN_CBS;
+ return (block*CBS_PER_OPAGE) + WCB_COUNTER_CBS + index;
+ }
+ return -1;
+}
+
+static void chainSetVal(int n, uint32_t val)
+{
+ int block, index;
+ uint32_t *p;
+
+ if (n < (WCB_CHAIN_OOL * PI_WAVE_COUNT_PAGES))
+ {
+ block = n / WCB_CHAIN_OOL;
+ index = n % WCB_CHAIN_OOL;
+ p = (uint32_t *) dmaOVirt[block] + (WCB_COUNTER_CBS+WCB_CHAIN_CBS) * 8;
+ p[index] = val;
+ }
+}
+
+static uint32_t chainGetValPadr(int n)
+{
+ int block, index;
+ uint32_t *p;
+
+ if (n < (WCB_CHAIN_OOL * PI_WAVE_COUNT_PAGES))
+ {
+ block = n / WCB_CHAIN_OOL;
+ index = n % WCB_CHAIN_OOL;
+ p = (uint32_t *) dmaOBus[block] + (WCB_COUNTER_CBS+WCB_CHAIN_CBS) * 8;
+ return (uint32_t) (p + index);
+ }
+ return 0;
+}
+
+static uint32_t chainGetCntVal(int counter, int slot)
+{
+ uint32_t *p;
+ int page, offset;
+ page = counter / 2;
+ offset = (counter % 2 ? WCB_COUNTER_OOL : 0);
+ p = (uint32_t *) dmaOVirt[page] + (WCB_COUNTER_CBS+WCB_CHAIN_CBS) * 8;
+ return p[WCB_CHAIN_OOL+ offset + slot];
+}
+
+static void chainSetCntVal(int counter, int slot, uint32_t value)
+{
+ uint32_t *p;
+ int page, offset;
+ page = counter / 2;
+ offset = (counter % 2 ? WCB_COUNTER_OOL : 0);
+ p = (uint32_t *) dmaOVirt[page] + (WCB_COUNTER_CBS+WCB_CHAIN_CBS) * 8;
+ p[WCB_CHAIN_OOL + offset + slot] = value;
+}
+
+static uint32_t chainGetCntValPadr(int counter, int slot)
+{
+ uint32_t *p;
+ int page, offset;
+ page = counter / 2;
+ offset = (counter % 2 ? WCB_COUNTER_OOL : 0);
+ p = (uint32_t *) dmaOBus[page] + (WCB_COUNTER_CBS+WCB_CHAIN_CBS) * 8;
+ return (uint32_t)(p + WCB_CHAIN_OOL + offset + slot);
+}
+
+static int chainGetCntCB(int counter)
+{
+ int page, offset;
+ page = counter / 2;
+ offset = (counter % 2 ? WCB_CNT_CBS : 0);
+ return ((page * CBS_PER_OPAGE) + offset);
+}
+
+static void chainMakeCounter(
+ unsigned counter,
+ unsigned blklen,
+ unsigned blocks,
+ unsigned count,
+ uint32_t repeat,
+ uint32_t next)
+{
+ rawCbs_t *p=NULL;
+
+ int b, baseCB, dig;
+ uint32_t nxt;
+
+ int botCB;
+
+ botCB = chainGetCntCB(counter);
+
+ baseCB = botCB;
+
+ /* set up all the OOLs */
+ for (b=0; b < (blocks*(blklen+1)); b++) chainSetCntVal(counter, b, repeat);
+
+ for (b=0; b<blocks; b++)
+ chainSetCntVal(counter,
+ ((b*(blklen+1))+blklen),
+ waveCbPOadr(baseCB+((b*3)+3)));
+
+ for (b=0; b<blocks; b++)
+ {
+ /* copy BOTTOM to NEXT */
+
+ p = rawWaveCBAdr(botCB++);
+
+ p->info = NORMAL_DMA;
+
+ p->src = chainGetCntValPadr(counter, b*(blklen+1));
+ p->dst = (waveCbPOadr(botCB+1) + 20);
+
+ p->length = 4;
+ p->next = waveCbPOadr(botCB);
+
+ /* copy BOTTOM to TOP */
+
+ p = rawWaveCBAdr(botCB++);
+
+ p->info = NORMAL_DMA;
+
+ p->src = chainGetCntValPadr(counter, b*(blklen+1));
+ p->dst = chainGetCntValPadr(counter, (b*(blklen+1))+blklen);
+
+ p->length = 4;
+ p->next = waveCbPOadr(botCB);
+
+ /* shift all down one */
+
+ p = rawWaveCBAdr(botCB++);
+
+ p->info = NORMAL_DMA|DMA_SRC_INC|DMA_DEST_INC;
+
+ p->src = chainGetCntValPadr(counter, ((b*(blklen+1))+1));
+ p->dst = chainGetCntValPadr(counter, ((b*(blklen+1))+0));
+
+ p->length = blklen*4;
+ p->next = repeat;
+ }
+
+ /* reset the counter */
+
+ p = rawWaveCBAdr(botCB);
+
+ p->info = NORMAL_DMA|DMA_SRC_INC|DMA_DEST_INC;
+
+ p->src = chainGetCntValPadr(counter, blocks*(blklen+1));
+ p->dst = chainGetCntValPadr(counter, 0);
+
+ p->length = blocks*(blklen+1)*4;
+ p->next = next;
+
+ b = 0;
+
+ while (count && (b<blocks))
+ {
+ dig = count % blklen;
+ count /= blklen;
+
+ if (count) nxt = chainGetCntVal(counter, (b*(blklen+1))+blklen);
+ else nxt = waveCbPOadr(botCB);
+
+ chainSetCntVal(counter, b*(blklen+1)+dig, nxt);
+
+ b++;
+ }
+
+ /* copy all the OOLs */
+ for (b=0; b < (blocks*(blklen+1)); b++)
+ chainSetCntVal(
+ counter, b+(blocks*(blklen+1)), chainGetCntVal(counter, b));
+}
+
+
int gpioWaveChain(char *buf, unsigned bufSize)
{
- unsigned blklen=8, blocks=8;
- int i, wid, rwid, nwid, firstCB, lastCB, counters, cycles;
+ unsigned blklen=16, blocks=4;
+ int cb, chaincb;
+ rawCbs_t *p;
+ int i, wid, cmd, loop, counters;
+ unsigned cycles;
uint32_t repeat, next;
- char used[256];
+ int stk_pos[10], stk_lev=0;
- rawCbs_t *p=NULL;
+ cb = 0;
+ loop = -1;
DBG(DBG_USER, "bufSize=%d [%s]", bufSize, myBuf2Str(bufSize, buf));
dmaOut[DMA_CONBLK_AD] = 0;
- for (i=0; i<256; i++) used[i] = 255;
+ /* add delay cb at start of DMA */
+
+ p = rawWaveCBAdr(chainGetCB(cb++));
+
+ /* use the secondary clock */
+
+ if (gpioCfg.clockPeriph != PI_CLOCK_PCM)
+ {
+ p->info = NORMAL_DMA | TIMED_DMA(2);
+ p->dst = PCM_TIMER;
+ }
+ else
+ {
+ p->info = NORMAL_DMA | TIMED_DMA(5);
+ p->dst = PWM_TIMER;
+ }
+
+ p->src = (uint32_t) (&dmaOBus[0]->periphData);
+ p->length = 4 * 20 / PI_WF_MICROS; /* 20 micros delay */
+ p->next = waveCbPOadr(chainGetCB(cb));
counters = 0;
wid = -1;
- lastCB = -1;
- firstCB = -1;
i = 0;
{
wid = (unsigned)buf[i];
- if (wid == 255) /* repeat wave command */
+ if (wid == 255) /* wave command */
{
- if (counters < PI_WAVE_COUNTERS)
+ if ((i+2) > bufSize)
+ SOFT_ERROR(PI_BAD_CHAIN_CMD,
+ "incomplete chain command (at %d)", i);
+
+ cmd = buf[i+1];
+
+ if (cmd == 0) /* loop begin */
{
- if ((i+4) < bufSize)
+ if (stk_lev >= (sizeof(stk_pos)/sizeof(int)))
+ SOFT_ERROR(PI_CHAIN_NESTING,
+ "chain counters nested too deep (at %d)", i);
+
+ stk_pos[stk_lev++] = cb;
+ i += 2;
+ }
+ else if (cmd == 1) /* loop end */
+ {
+ if (counters >= WCB_COUNTERS)
+ SOFT_ERROR(PI_CHAIN_COUNTER,
+ "too many chain counters (at %d)", i);
+
+ if ((i+4) > bufSize)
+ SOFT_ERROR(PI_BAD_CHAIN_CMD,
+ "incomplete chain command (at %d)", i);
+
+ loop = 0;
+ if (--stk_lev >= 0) loop = stk_pos[stk_lev];
+
+ if ((loop < 1) || (loop == cb))
+ SOFT_ERROR(PI_BAD_CHAIN_LOOP,
+ "empty chain loop (at %d)", i);
+
+ cycles = ((unsigned)buf[i+3] << 8) + (unsigned)buf[i+2];
+
+ i += 4;
+
+ if (cycles > PI_MAX_WAVE_CYCLES)
+ SOFT_ERROR(PI_CHAIN_LOOP_CNT,
+ "bad chain loop count (%d)", cycles);
+
+ if (cycles == 0)
{
- rwid = buf[i+1];
- if ((i+5) < bufSize)
- {
- nwid = buf[i+5];
- if (nwid < waveOutCount)
- next = waveCbPOadr(1+waveInfo[nwid].botCB);
- else next = 0; /* error, will be picked up later */
- }
- else next = 0;
- if (used[rwid] == counters)
- {
- repeat = waveCbPOadr(1+waveInfo[rwid].botCB);
+ /* Skip the complete loop block. Change
+ the next pointing to the start of the
+ loop block to the current cb.
+ */
+ p = rawWaveCBAdr(chainGetCB(loop));
+ p->next = waveCbPOadr(chainGetCB(cb));
+ }
+ else if (cycles == 1)
+ {
+ /* Nothing to do, no need for a counter. */
+ }
+ else
+ {
+ chaincb = chainGetCB(cb++);
+ if (chaincb < 0)
+ SOFT_ERROR(PI_CHAIN_TOO_BIG, "chain is too long (%d)", cb);
- cycles = (unsigned)buf[i+2] +
- ((unsigned)buf[i+3]<<8) +
- ((unsigned)buf[i+4]<<16);
+ p = rawWaveCBAdr(chaincb);
- i+=4;
+ repeat = waveCbPOadr(chainGetCB(loop));
- if ((cycles > 1) && (cycles < PI_MAX_WAVE_CYCLES))
- {
- --cycles;
+ /* Need to check next cb as well. */
- waveCount(counters, blklen, blocks, cycles, repeat, next);
+ chaincb = chainGetCB(cb);
- p = rawWaveCBAdr(lastCB);
+ if (chaincb < 0)
+ SOFT_ERROR(PI_CHAIN_TOO_BIG, "chain is too long (%d)", cb);
- lastCB = -1;
+ next = waveCbPOadr(chainGetCB(cb));
- p->next = waveCbPOadr(counters * CBS_PER_OPAGE);
+ /* dummy src and dest */
+ p->info = NORMAL_DMA;
+ p->src = (uint32_t) (&dmaOBus[0]->periphData);
+ p->dst = (uint32_t) (&dmaOBus[0]->periphData);
+ p->length = 4;
+ p->next = waveCbPOadr(chainGetCntCB(counters));
- counters++;
- }
- else SOFT_ERROR(PI_BAD_REPEAT_CNT,
- "bad chain repeat count (%d)", cycles);
+ chainMakeCounter(counters, blklen, blocks,
+ cycles-1, repeat, next);
+
+ counters++;
+ }
+ loop = -1;
+ }
+ else if (cmd == 2) /* delay us */
+ {
+ if ((i+4) > bufSize)
+ SOFT_ERROR(PI_BAD_CHAIN_CMD,
+ "incomplete chain command (at %d)", i);
+
+ cycles = ((unsigned)buf[i+3] << 8) + (unsigned)buf[i+2];
+
+ i += 4;
+
+ if (cycles > PI_MAX_WAVE_DELAY)
+ SOFT_ERROR(PI_BAD_CHAIN_DELAY,
+ "bad chain delay micros (%d)", cycles);
+
+ if (cycles)
+ {
+ chaincb = chainGetCB(cb++);
+
+ if (chaincb < 0)
+ SOFT_ERROR(PI_CHAIN_TOO_BIG, "chain is too long (%d)", cb);
+
+ p = rawWaveCBAdr(chaincb);
+
+ /* use the secondary clock */
+
+ if (gpioCfg.clockPeriph != PI_CLOCK_PCM)
+ {
+ p->info = NORMAL_DMA | TIMED_DMA(2);
+ p->dst = PCM_TIMER;
}
- else SOFT_ERROR(PI_BAD_REPEAT_WID,
- "bad chain repeat wave (%d)", rwid);
+ else
+ {
+ p->info = NORMAL_DMA | TIMED_DMA(5);
+ p->dst = PWM_TIMER;
+ }
+
+ p->src = (uint32_t) (&dmaOBus[0]->periphData);
+ p->length = 4 * cycles / PI_WF_MICROS;
+ p->next = waveCbPOadr(chainGetCB(cb));
}
- else SOFT_ERROR(PI_BAD_CHAIN_CMD,
- "bad chain command (at char %d)", i);
}
- else SOFT_ERROR(PI_TOO_MANY_COUNTS,
- "too many chain counters (at char %d)", i);
+ else
+ SOFT_ERROR(PI_BAD_CHAIN_CMD,
+ "unknown chain command (255 %d)", cmd);
}
- else if (wid >= waveOutCount)
+ else if ((wid >= waveOutCount) || waveInfo[wid].deleted)
SOFT_ERROR(PI_BAD_WAVE_ID, "undefined wave (%d)", wid);
else
{
- if (used[wid] == 255)
- {
- used[wid] = counters;
+ chaincb = chainGetCB(cb++);
- if (firstCB < 0) firstCB = waveInfo[wid].botCB;
+ if (chaincb < 0)
+ SOFT_ERROR(PI_CHAIN_TOO_BIG, "chain is too long (%d)", cb);
- if (lastCB >= 0)
- {
- p = rawWaveCBAdr(lastCB);
+ p = rawWaveCBAdr(chaincb);
- p->next = waveCbPOadr(1+waveInfo[wid].botCB);
- }
- lastCB = waveInfo[wid].topCB;
- }
- else SOFT_ERROR(PI_REUSED_WID,
- "wave already used in chain (%d)", wid);
+ chaincb = chainGetCB(cb);
+
+ if (chaincb < 0)
+ SOFT_ERROR(PI_CHAIN_TOO_BIG, "chain is too long (%d)", cb);
+
+ chainSetVal(cb-1, waveCbPOadr(chaincb));
+
+ /* patch next of wid topCB to next cb */
+
+ p->info = NORMAL_DMA;
+ p->src = chainGetValPadr(cb-1); /* this next */
+ p->dst = waveCbPOadr(waveInfo[wid].topCB) + 20; /* wid next */
+ p->length = 4;
+ p->next = waveCbPOadr(waveInfo[wid].botCB+1);
+
+ i += 1;
}
- i++;
}
- if (firstCB >= 0)
- {
- if (lastCB >= 0)
- {
- p = rawWaveCBAdr(lastCB);
+ chaincb = chainGetCB(cb++);
- p->next = 0;
- }
+ if (chaincb < 0)
+ SOFT_ERROR(PI_CHAIN_TOO_BIG, "chain is too long (%d)", cb);
- initDMAgo((uint32_t *)dmaOut, waveCbPOadr(firstCB));
- }
+ p = rawWaveCBAdr(chaincb);
+
+ p->info = NORMAL_DMA;
+ p->src = (uint32_t) (&dmaOBus[0]->periphData);
+ p->dst = (uint32_t) (&dmaOBus[0]->periphData);
+ p->length = 4;
+ p->next = 0;
+
+ initDMAgo((uint32_t *)dmaOut, waveCbPOadr(chainGetCB(0)));
return 0;
}
#include <stdint.h>
#include <pthread.h>
-#define PIGPIO_VERSION 34
+#define PIGPIO_VERSION 35
/*TEXT
gpioWaveAddSerial Adds serial data to the waveform
gpioWaveCreate Creates a waveform from added data
-gpioWaveDelete Deletes one or more waveforms
+gpioWaveDelete Deletes a waveform
gpioWaveTxSend Transmits a waveform
gpioWaveGetHighCbs Length of longest waveform so far
gpioWaveGetMaxCbs Absolute maximum allowed control blocks
-gpioWaveTxStart Creates/transmits a waveform (DEPRECATED)
-
I2C
i2cOpen Opens an I2C device
uint32_t flags;
} rawWave_t;
+/*
+CBs are used in order from the lowest numbered CB up to
+the maximum NUM_WAVE_CBS.
+
+OOLS are used from the bottom climbing up and from
+the top climbing down.
+
+The gpio on and off settings climb up from the bottom (botOOL/numBOOL).
+
+The level and tick read values are stored in descending locations
+from the top (topOOL/numTOOL).
+*/
+
typedef struct
{
uint16_t botCB; /* first CB used by wave */
uint16_t topCB; /* last CB used by wave */
- uint16_t botOOL; /* last OOL used by wave */
- uint16_t topOOL; /* first OOL used by wave */
+ uint16_t botOOL; /* first bottom OOL used by wave */
+ /* botOOL to botOOL + numBOOL -1 are in use */
+ uint16_t topOOL; /* last top OOL used by wave */
+ /* topOOL - numTOOL to topOOL are in use.*/
+ uint16_t deleted;
+ uint16_t numCB;
+ uint16_t numBOOL;
+ uint16_t numTOOL;
} rawWaveInfo_t;
typedef struct
#define PI_WAVE_MAX_MICROS (30 * 60 * 1000000) /* half an hour */
-#define PI_MAX_WAVES 250
-//#define PI_MAX_WAVE_CYCLES 537824
-#define PI_MAX_WAVE_CYCLES 16777216
-#define PI_WAVE_COUNTERS 5
+#define PI_MAX_WAVES 250
+
+#define PI_MAX_WAVE_CYCLES 65535
+#define PI_MAX_WAVE_DELAY 65535
+
+#define PI_WAVE_COUNT_PAGES 10
/* wave tx mode */
int gpioWaveCreate(void);
/*D
This function creates a waveform from the data provided by the prior
-calls to the [*gpioWaveAdd**] functions. Upon success a positive wave id
-is returned.
+calls to the [*gpioWaveAdd**] functions. Upon success a wave id
+greater than or equal to 0 is returned, otherwise PI_EMPTY_WAVEFORM,
+PI_TOO_MANY_CBS, PI_TOO_MANY_OOL, or PI_NO_WAVEFORM_ID.
The data provided by the [*gpioWaveAdd**] functions is consumed by this
function.
/*F*/
int gpioWaveDelete(unsigned wave_id);
/*D
-This function deletes all created waveforms with ids greater than or
-equal to wave_id.
+This function deletes the waveform with id wave_id.
. .
wave_id: >=0, as returned by [*gpioWaveCreate*]
D*/
-/*F*/
-int gpioWaveTxStart(unsigned wave_mode); /* DEPRECATED */
-/*D
-This function creates and then transmits a waveform. The mode
-determines whether the waveform is sent once or cycles endlessly.
-
-NOTE: Any hardware PWM started by [*gpioHardwarePWM*] will be cancelled.
-
-. .
-wave_mode: 0 (PI_WAVE_MODE_ONE_SHOT), 1 (PI_WAVE_MODE_REPEAT)
-. .
-
-This function is deprecated and should no longer be used. Use
-[*gpioWaveCreate*] and [*gpioWaveTxSend*] instead.
-
-Returns the number of DMA control blocks in the waveform if OK,
-otherwise PI_BAD_WAVE_MODE.
-D*/
-
-
/*F*/
int gpioWaveTxSend(unsigned wave_id, unsigned wave_mode);
/*D
NOTE: Any hardware PWM started by [*gpioHardwarePWM*] will be cancelled.
The waves to be transmitted are specified by the contents of buf
-which contains an ordered list of wave_ids and optional command
+which contains an ordered list of [*wave_id*]s and optional command
codes and related data.
. .
bufSize: the number of bytes in buf
. .
-Returns 0 if OK, otherwise PI_BAD_REPEAT_CNT, PI_BAD_REPEAT_WID,
-PI_BAD_CHAIN_CMD, PI_TOO_MANY_COUNTS, or PI_BAD_WAVE_ID.
+Returns 0 if OK, otherwise PI_CHAIN_NESTING, PI_CHAIN_LOOP_CNT, PI_BAD_CHAIN_LOOP, PI_BAD_CHAIN_CMD, PI_CHAIN_COUNTER,
+PI_BAD_CHAIN_DELAY, PI_CHAIN_TOO_BIG, or PI_BAD_WAVE_ID.
-Each wave is transmitted in the order specified. A wave may only
-occur once per chain. Waves may be transmitted multiple times by
-using the repeat command. The repeat command specifies a wave id
-and a count. The wave id must occur earlier in the chain. All the
-waves between wave id and the repeat command are transmitted count
-times.
+Each wave is transmitted in the order specified. A wave may
+occur multiple times per chain.
-Repeat commands may not be nested. The minimum repeat count is 2.
-A maximum of 5 repeat commands is supported per chain.
+A blocks of waves may be transmitted multiple times by using
+the loop commands. The block is bracketed by loop start and
+end commands. Loops may be nested.
+
+Delays between waves may be added with the delay command.
The following command codes are supported:
-Name @ Cmd & Data @ Meaning
-Repeat @ 255 wid C0 C1 C2 @ Repeat from wid count times
-count = C0 + C1*256 + C2*65536
+Name @ Cmd & Data @ Meaning
+Loop Start @ 255 0 @ Identify start of a wave block
+Loop Repeat @ 255 1 x y @ loop x + y*256 times
+Delay @ 255 2 x y @ delay x + y*256 microseconds
+
+The code is currently dimensioned to support a chain with roughly
+600 entries and 20 loop counters.
...
-The following examples assume that waves with ids 0 to 12 exist.
+#include <stdio.h>
+#include <pigpio.h>
+
+#define WAVES 5
+#define GPIO 4
+
+int main(int argc, char *argv[])
+{
+ int i, wid[WAVES];
+
+ if (gpioInitialise()<0) return -1;
+
+ gpioSetMode(GPIO, PI_OUTPUT);
+
+ printf("start piscope, press return\n"); getchar();
+
+ for (i=0; i<WAVES; i++)
+ {
+ gpioWaveAddGeneric(2, (gpioPulse_t[])
+ {{1<<GPIO, 0, 20},
+ {0, 1<<GPIO, (i+1)*200}});
+
+ wid[i] = gpioWaveCreate();
+ }
-// 0 255 0 57 0 0 (repeat 0 57 times)
-status = gpioWaveChain((char []){0, 255, 0, 57, 0, 0}, 6);
+ gpioWaveChain((char []) {
+ wid[4], wid[3], wid[2], // transmit waves 4+3+2
+ 255, 0, // loop start
+ wid[0], wid[0], wid[0], // transmit waves 0+0+0
+ 255, 0, // loop start
+ wid[0], wid[1], // transmit waves 0+1
+ 255, 2, 0x88, 0x13, // delay 5000us
+ 255, 1, 30, 0, // loop end (repeat 30 times)
+ 255, 0, // loop start
+ wid[2], wid[3], wid[0], // transmit waves 2+3+0
+ wid[3], wid[1], wid[2], // transmit waves 3+1+2
+ 255, 1, 10, 0, // loop end (repeat 10 times)
+ 255, 1, 5, 0, // loop end (repeat 5 times)
+ wid[4], wid[4], wid[4], // transmit waves 4+4+4
+ 255, 2, 0x20, 0x4E, // delay 20000us
+ wid[0], wid[0], wid[0], // transmit waves 0+0+0
-// 0 1 255 0 0 2 0 (repeat 0+1 512 times)
-status = gpioWaveChain((char []){0, 1, 255, 0, 0, 2, 0}, 7);
+ }, 46);
-// 0 1 255 1 0 0 1 (transmit 0, repeat 1 65536 times)
-status = gpioWaveChain((char []){0, 1, 255, 1, 0, 0, 1}, 7);
+ while (gpioWaveTxBusy()) time_sleep(0.1);
-// 0 1 2 3 255 2 13 0 0 (transmit 0+1, repeat 2+3 13 times)
-status = gpioWaveChain(
- (char []){0, 1, 2, 3, 255, 2, 13, 0, 0}, 9);
+ for (i=0; i<WAVES; i++) gpioWaveDelete(wid[i]);
-// The following repeats 5 65793 times, transmits 6,
-// repeats 7+8 514 times, transmits 12,
-// repeats 9+11+10 197121 times.
-// 5 255 5 1 1 1 6 7 8 255 7 2 2 0 12 9 11 10 255 9 1 2 3
-char chain[] = {
- 5, 255, 5, 1, 1, 1,
- 6, 7, 8, 255, 7, 2, 2, 0,
- 12, 9, 11, 10, 255, 9, 1, 2, 3};
+ printf("stop piscope, press return\n"); getchar();
-status = gpioWaveChain(chain, sizeof(chain));
+ gpioTerminate();
+}
...
D*/
Starts hardware PWM on a gpio at the specified frequency and dutycycle.
Frequencies above 30MHz are unlikely to work.
-NOTE: Any waveform started by [*gpioWaveTxSend*], [*gpioWaveTxStart*],
-or [*gpioWaveChain*] will be cancelled.
+NOTE: Any waveform started by [*gpioWaveTxSend*], or
+[*gpioWaveChain*] will be cancelled.
This function is only valid if the pigpio main clock is PCM. The
main clock defaults to PCM but may be overridden by a call to
wave_id::
-A number representing a waveform created by [*gpioWaveCreate*].
+A number identifying a waveform created by [*gpioWaveCreate*].
wave_mode::
#define PI_BAD_I2C_RLEN -110 // bad I2C read length
#define PI_BAD_I2C_CMD -111 // bad I2C command
#define PI_BAD_I2C_BAUD -112 // bad I2C baud rate, not 50-500k
-#define PI_BAD_REPEAT_CNT -113 // bad repeat count, not 2-max
-#define PI_BAD_REPEAT_WID -114 // bad repeat wave id
-#define PI_TOO_MANY_COUNTS -115 // too many chain counters
-#define PI_BAD_CHAIN_CMD -116 // malformed chain command string
-#define PI_REUSED_WID -117 // wave already used in chain
+#define PI_CHAIN_LOOP_CNT -113 // bad chain loop count
+#define PI_BAD_CHAIN_LOOP -114 // empty chain loop
+#define PI_CHAIN_COUNTER -115 // too many chain counters
+#define PI_BAD_CHAIN_CMD -116 // bad chain command
+#define PI_BAD_CHAIN_DELAY -117 // bad chain delay micros
+#define PI_CHAIN_NESTING -118 // chain counters nested too deeply
+#define PI_CHAIN_TOO_BIG -119 // chain is too long
+#define PI_DEPRECATED -120 // deprecated function removed
#define PI_PIGIF_ERR_0 -2000
#define PI_PIGIF_ERR_99 -2099
wave_tx_busy Checks to see if a waveform has ended
wave_tx_stop Aborts the current waveform
-wave_tx_repeat Creates/transmits a waveform (DEPRECATED)
-wave_tx_start Creates/transmits a waveform (DEPRECATED)
-
wave_get_micros Length in microseconds of the current waveform
wave_get_max_micros Absolute maximum allowed micros
wave_get_pulses Length in pulses of the current waveform
import os
import atexit
-VERSION = "1.19"
+VERSION = "1.20"
exceptions = True
PI_BAD_I2C_RLEN =-110
PI_BAD_I2C_CMD =-111
PI_BAD_I2C_BAUD =-112
-PI_BAD_REPEAT_CNT =-113
-PI_BAD_REPEAT_WID =-114
-PI_TOO_MANY_COUNTS =-115
+PI_CHAIN_LOOP_CNT =-113
+PI_BAD_CHAIN_LOOP =-114
+PI_CHAIN_COUNTER =-115
PI_BAD_CHAIN_CMD =-116
-PI_REUSED_WID =-117
+PI_BAD_CHAIN_DELAY =-117
+PI_CHAIN_NESTING =-118
+PI_CHAIN_TOO_BIG =-119
+PI_DEPRECATED =-120
# pigpio error text
[PI_BAD_I2C_RLEN , "bad I2C read length"],
[PI_BAD_I2C_CMD , "bad I2C command"],
[PI_BAD_I2C_BAUD , "bad I2C baud rate, not 50-500k"],
- [PI_BAD_REPEAT_CNT , "bad repeat count, not 2-max"],
- [PI_BAD_REPEAT_WID , "bad repeat wave id"],
- [PI_TOO_MANY_COUNTS , "too many chain counters"],
- [PI_BAD_CHAIN_CMD , "malformed chain command string"],
- [PI_REUSED_WID , "wave already used in chain"],
+ [PI_CHAIN_LOOP_CNT , "bad chain loop count"],
+ [PI_BAD_CHAIN_LOOP , "empty chain loop"],
+ [PI_CHAIN_COUNTER , "too many chain counters"],
+ [PI_BAD_CHAIN_CMD , "bad chain command"],
+ [PI_BAD_CHAIN_DELAY , "bad chain delay micros"],
+ [PI_CHAIN_NESTING , "chain counters nested too deeply"],
+ [PI_CHAIN_TOO_BIG , "chain is too long"],
+ [PI_DEPRECATED , "deprecated function removed"],
]
and dutycycle. Frequencies above 30MHz are unlikely to work.
NOTE: Any waveform started by [*wave_send_once*],
- [*wave_send_repeat*], [*wave_tx_start*], [*wave_tx_repeat*],
- or [*wave_chain*] will be cancelled.
+ [*wave_send_repeat*], or [*wave_chain*] will be cancelled.
This function is only valid if the pigpio main clock is PCM.
The main clock defaults to PCM but may be overridden when the
Creates a waveform from the data provided by the prior calls
to the [*wave_add_**] functions.
- Returns a wave id (>=0) if OK.
+ Returns a wave id (>=0) if OK, otherwise PI_EMPTY_WAVEFORM,
+ PI_TOO_MANY_CBS, PI_TOO_MANY_OOL, or PI_NO_WAVEFORM_ID.
The data provided by the [*wave_add_**] functions is consumed by
this function.
def wave_delete(self, wave_id):
"""
- Deletes all created waveforms with ids greater than or equal
- to wave_id.
+ This function deletes the waveform with id wave_id.
wave_id:= >=0 (as returned by a prior call to [*wave_create*]).
Wave ids are allocated in order, 0, 1, 2, etc.
...
- pi.wave_delete(6) # delete all waves with id 6 or greater
+ pi.wave_delete(6) # delete waveform with id 6
- pi.wave_delete(0) # delete all waves
+ pi.wave_delete(0) # delete waveform with id 0
...
"""
return _u2i(_pigpio_command(self.sl, _PI_CMD_WVDEL, wave_id, 0))
def wave_tx_start(self): # DEPRECATED
"""
- This function is deprecated and will be removed.
+ This function is deprecated and has been removed.
Use [*wave_create*]/[*wave_send_**] instead.
-
- NOTE: Any hardware PWM started by [*hardware_PWM*] will
- be cancelled.
"""
return _u2i(_pigpio_command(self.sl, _PI_CMD_WVGO, 0, 0))
def wave_tx_repeat(self): # DEPRECATED
"""
- This function is deprecated and will be removed.
+ This function is deprecated and has beeen removed.
Use [*wave_create*]/[*wave_send_**] instead.
-
- NOTE: Any hardware PWM started by [*hardware_PWM*] will
- be cancelled.
"""
return _u2i(_pigpio_command(self.sl, _PI_CMD_WVGOR, 0, 0))
"""
This function transmits a chain of waveforms.
- NOTE: Any hardware PWM started by [*hardware_PWM*] will
- be cancelled.
+ NOTE: Any hardware PWM started by [*hardware_PWM*]
+ will be cancelled.
- The waves to be transmitted are specified by the contents of
- data which contains an ordered list of wave_ids and optional
- command codes and related data.
+ The waves to be transmitted are specified by the contents
+ of data which contains an ordered list of [*wave_id*]s
+ and optional command codes and related data.
- data:= contains the wave_ids and optional command codes
+ Returns 0 if OK, otherwise PI_CHAIN_NESTING,
+ PI_CHAIN_LOOP_CNT, PI_BAD_CHAIN_LOOP, PI_BAD_CHAIN_CMD,
+ PI_CHAIN_COUNTER, PI_BAD_CHAIN_DELAY, PI_CHAIN_TOO_BIG,
+ or PI_BAD_WAVE_ID.
- Returns 0 if OK, otherwise PI_BAD_REPEAT_CNT, PI_BAD_REPEAT_WID,
- PI_BAD_CHAIN_CMD, PI_TOO_MANY_COUNTS, or PI_BAD_WAVE_ID.
+ Each wave is transmitted in the order specified. A wave
+ may occur multiple times per chain.
- Each wave is transmitted in the order specified. A wave may
- only occur once per chain. Waves may be transmitted multiple
- times by using the repeat command. The repeat command
- specifies a wave id and a count. The wave id must occur
- earlier in the chain. All the waves between wave id and the
- repeat command are transmitted count times.
+ A blocks of waves may be transmitted multiple times by
+ using the loop commands. The block is bracketed by loop
+ start and end commands. Loops may be nested.
- Repeat commands may not be nested. The minimum repeat
- count is 2. A maximum of 5 repeat commands is supported
- per chain.
+ Delays between waves may be added with the delay command.
The following command codes are supported:
- Name @ Cmd & Data @ Meaning
- Repeat @ 255 wid C0 C1 C2 @ Repeat from wid count times
- count = C0 + C1*256 + C2*65536
+ Name @ Cmd & Data @ Meaning
+ Loop Start @ 255 0 @ Identify start of a wave block
+ Loop Repeat @ 255 1 x y @ loop x + y*256 times
+ Delay @ 255 2 x y @ delay x + y*256 microseconds
+
+ The code is currently dimensioned to support a chain with
+ roughly 600 entries and 20 loop counters.
...
- The following examples assume that waves with ids 0 to 12 exist.
+ #!/usr/bin/env python
+
+ import time
+ import pigpio
+
+ WAVES=5
+ GPIO=4
- # 0 255 0 57 0 0 (repeat 0 57 times)
- pi.wave_chain([0, 255, 0, 57, 0, 0])
+ wid=[0]*WAVES
- # 0 1 255 0 0 2 0 (repeat 0+1 512 times)
- pi.wave_chain([0, 1, 255, 0, 0, 2, 0])
+ pi = pigpio.pi() # Connect to local Pi.
- # 0 1 255 1 0 0 1 (transmit 0, repeat 1 65536 times)
- pi.wave_chain([0, 1, 255, 1, 0, 0, 1])
+ pi.set_mode(GPIO, pigpio.OUTPUT);
- # 0 1 2 3 255 2 13 0 0 (transmit 0+1, repeat 2+3 13 times)
- pi.wave_chain([0, 1, 2, 3, 255, 2, 13, 0, 0])
+ for i in range(WAVES):
+ pi.wave_add_generic([
+ pigpio.pulse(1<<GPIO, 0, 20),
+ pigpio.pulse(0, 1<<GPIO, (i+1)*200)]);
+
+ wid[i] = pi.wave_create();
- # The following repeats 5 65793 times, transmits 6,
- # repeats 7+8 514 times, transmits 12,
- # repeats 9+11+10 197121 times.
- # 5 255 5 1 1 1 6 7 8 255 7 2 2 0 12 9 11 10 255 9 1 2 3
pi.wave_chain([
- 5, 255, 5, 1, 1, 1,
- 6, 7, 8, 255, 7, 2, 2, 0,
- 12, 9, 11, 10, 255, 9, 1, 2, 3])
+ wid[4], wid[3], wid[2], # transmit waves 4+3+2
+ 255, 0, # loop start
+ wid[0], wid[0], wid[0], # transmit waves 0+0+0
+ 255, 0, # loop start
+ wid[0], wid[1], # transmit waves 0+1
+ 255, 2, 0x88, 0x13, # delay 5000us
+ 255, 1, 30, 0, # loop end (repeat 30 times)
+ 255, 0, # loop start
+ wid[2], wid[3], wid[0], # transmit waves 2+3+0
+ wid[3], wid[1], wid[2], # transmit waves 3+1+2
+ 255, 1, 10, 0, # loop end (repeat 10 times)
+ 255, 1, 5, 0, # loop end (repeat 5 times)
+ wid[4], wid[4], wid[4], # transmit waves 4+4+4
+ 255, 2, 0x20, 0x4E, # delay 20000us
+ wid[0], wid[0], wid[0], # transmit waves 0+0+0
+ ])
+
+ while pi.wave_tx_busy():
+ time.sleep(0.1);
+
+ for i in range(WAVES):
+ pi.wave_delete(wid[i])
+
+ pi.stop()
...
"""
# I p1 0
edge:= EITHER_EDGE, RISING_EDGE (default), or FALLING_EDGE.
func:= user supplied callback function.
- If a user callback is not specified a default tally callback is
- provided which simply counts edges.
-
The user supplied callback receives three parameters, the gpio,
the level, and the tick.
+ If a user callback is not specified a default tally callback is
+ provided which simply counts edges. The count may be retrieved
+ by calling the tally function.
+
+ The callback may be cancelled by calling the cancel function.
+
+ A gpio may have multiple callbacks (although I can't think of
+ a reason to do so).
+
...
def cbf(gpio, level, tick):
print(gpio, level, tick)
cb3 = pi.callback(17)
print(cb3.tally())
+
+ cb1.cancel() # To cancel callback cb1.
...
"""
return _callback(self._notify, user_gpio, edge, func)
RISING_EDGE = 0
errnum: <0
+
. .
- PI_BAD_USER_GPIO =-2
- PI_BAD_GPIO =-3
- PI_BAD_MODE =-4
- PI_BAD_LEVEL =-5
- PI_BAD_PUD =-6
- PI_BAD_PULSEWIDTH =-7
- PI_BAD_DUTYCYCLE =-8
- PI_BAD_WDOG_TIMEOUT =-15
- PI_BAD_DUTYRANGE =-21
- PI_NO_HANDLE =-24
- PI_BAD_HANDLE =-25
- PI_BAD_WAVE_BAUD =-35
- PI_TOO_MANY_PULSES =-36
- PI_TOO_MANY_CHARS =-37
- PI_NOT_SERIAL_GPIO =-38
- PI_NOT_PERMITTED =-41
- PI_SOME_PERMITTED =-42
- PI_BAD_WVSC_COMMND =-43
- PI_BAD_WVSM_COMMND =-44
- PI_BAD_WVSP_COMMND =-45
- PI_BAD_PULSELEN =-46
- PI_BAD_SCRIPT =-47
- PI_BAD_SCRIPT_ID =-48
- PI_BAD_SER_OFFSET =-49
- PI_GPIO_IN_USE =-50
- PI_BAD_SERIAL_COUNT =-51
- PI_BAD_PARAM_NUM =-52
- PI_DUP_TAG =-53
- PI_TOO_MANY_TAGS =-54
- PI_BAD_SCRIPT_CMD =-55
- PI_BAD_VAR_NUM =-56
- PI_NO_SCRIPT_ROOM =-57
- PI_NO_MEMORY =-58
- PI_SOCK_READ_FAILED =-59
- PI_SOCK_WRIT_FAILED =-60
- PI_TOO_MANY_PARAM =-61
- PI_NOT_HALTED =-62
- PI_BAD_TAG =-63
- PI_BAD_MICS_DELAY =-64
- PI_BAD_MILS_DELAY =-65
- PI_BAD_WAVE_ID =-66
- PI_TOO_MANY_CBS =-67
- PI_TOO_MANY_OOL =-68
- PI_EMPTY_WAVEFORM =-69
- PI_NO_WAVEFORM_ID =-70
- PI_I2C_OPEN_FAILED =-71
- PI_SER_OPEN_FAILED =-72
- PI_SPI_OPEN_FAILED =-73
- PI_BAD_I2C_BUS =-74
- PI_BAD_I2C_ADDR =-75
- PI_BAD_SPI_CHANNEL =-76
- PI_BAD_FLAGS =-77
- PI_BAD_SPI_SPEED =-78
- PI_BAD_SER_DEVICE =-79
- PI_BAD_SER_SPEED =-80
- PI_BAD_PARAM =-81
- PI_I2C_WRITE_FAILED =-82
- PI_I2C_READ_FAILED =-83
- PI_BAD_SPI_COUNT =-84
- PI_SER_WRITE_FAILED =-85
- PI_SER_READ_FAILED =-86
- PI_SER_READ_NO_DATA =-87
- PI_UNKNOWN_COMMAND =-88
- PI_SPI_XFER_FAILED =-89
- PI_NO_AUX_SPI =-91
- PI_NOT_PWM_GPIO =-92
- PI_NOT_SERVO_GPIO =-93
- PI_NOT_HCLK_GPIO =-94
- PI_NOT_HPWM_GPIO =-95
- PI_BAD_HPWM_FREQ =-96
- PI_BAD_HPWM_DUTY =-97
- PI_BAD_HCLK_FREQ =-98
- PI_BAD_HCLK_PASS =-99
- PI_HPWM_ILLEGAL =-100
- PI_BAD_DATABITS =-101
- PI_BAD_STOPBITS =-102
- PI_MSG_TOOBIG =-103
- PI_BAD_MALLOC_MODE =-104
- PI_BAD_SMBUS_CMD =-107
- PI_NOT_I2C_GPIO =-108
- PI_BAD_I2C_WLEN =-109
- PI_BAD_I2C_RLEN =-110
- PI_BAD_I2C_CMD =-111
- PI_BAD_I2C_BAUD =-112
- PI_BAD_REPEAT_CNT =-113
- PI_BAD_REPEAT_WID =-114
- PI_TOO_MANY_COUNTS =-115
- PI_BAD_CHAIN_CMD =-116
- PI_REUSED_WID =-117
+ PI_BAD_USER_GPIO = -2
+ PI_BAD_GPIO = -3
+ PI_BAD_MODE = -4
+ PI_BAD_LEVEL = -5
+ PI_BAD_PUD = -6
+ PI_BAD_PULSEWIDTH = -7
+ PI_BAD_DUTYCYCLE = -8
+ PI_BAD_WDOG_TIMEOUT = -15
+ PI_BAD_DUTYRANGE = -21
+ PI_NO_HANDLE = -24
+ PI_BAD_HANDLE = -25
+ PI_BAD_WAVE_BAUD = -35
+ PI_TOO_MANY_PULSES = -36
+ PI_TOO_MANY_CHARS = -37
+ PI_NOT_SERIAL_GPIO = -38
+ PI_NOT_PERMITTED = -41
+ PI_SOME_PERMITTED = -42
+ PI_BAD_WVSC_COMMND = -43
+ PI_BAD_WVSM_COMMND = -44
+ PI_BAD_WVSP_COMMND = -45
+ PI_BAD_PULSELEN = -46
+ PI_BAD_SCRIPT = -47
+ PI_BAD_SCRIPT_ID = -48
+ PI_BAD_SER_OFFSET = -49
+ PI_GPIO_IN_USE = -50
+ PI_BAD_SERIAL_COUNT = -51
+ PI_BAD_PARAM_NUM = -52
+ PI_DUP_TAG = -53
+ PI_TOO_MANY_TAGS = -54
+ PI_BAD_SCRIPT_CMD = -55
+ PI_BAD_VAR_NUM = -56
+ PI_NO_SCRIPT_ROOM = -57
+ PI_NO_MEMORY = -58
+ PI_SOCK_READ_FAILED = -59
+ PI_SOCK_WRIT_FAILED = -60
+ PI_TOO_MANY_PARAM = -61
+ PI_NOT_HALTED = -62
+ PI_BAD_TAG = -63
+ PI_BAD_MICS_DELAY = -64
+ PI_BAD_MILS_DELAY = -65
+ PI_BAD_WAVE_ID = -66
+ PI_TOO_MANY_CBS = -67
+ PI_TOO_MANY_OOL = -68
+ PI_EMPTY_WAVEFORM = -69
+ PI_NO_WAVEFORM_ID = -70
+ PI_I2C_OPEN_FAILED = -71
+ PI_SER_OPEN_FAILED = -72
+ PI_SPI_OPEN_FAILED = -73
+ PI_BAD_I2C_BUS = -74
+ PI_BAD_I2C_ADDR = -75
+ PI_BAD_SPI_CHANNEL = -76
+ PI_BAD_FLAGS = -77
+ PI_BAD_SPI_SPEED = -78
+ PI_BAD_SER_DEVICE = -79
+ PI_BAD_SER_SPEED = -80
+ PI_BAD_PARAM = -81
+ PI_I2C_WRITE_FAILED = -82
+ PI_I2C_READ_FAILED = -83
+ PI_BAD_SPI_COUNT = -84
+ PI_SER_WRITE_FAILED = -85
+ PI_SER_READ_FAILED = -86
+ PI_SER_READ_NO_DATA = -87
+ PI_UNKNOWN_COMMAND = -88
+ PI_SPI_XFER_FAILED = -89
+ PI_NO_AUX_SPI = -91
+ PI_NOT_PWM_GPIO = -92
+ PI_NOT_SERVO_GPIO = -93
+ PI_NOT_HCLK_GPIO = -94
+ PI_NOT_HPWM_GPIO = -95
+ PI_BAD_HPWM_FREQ = -96
+ PI_BAD_HPWM_DUTY = -97
+ PI_BAD_HCLK_FREQ = -98
+ PI_BAD_HCLK_PASS = -99
+ PI_HPWM_ILLEGAL = -100
+ PI_BAD_DATABITS = -101
+ PI_BAD_STOPBITS = -102
+ PI_MSG_TOOBIG = -103
+ PI_BAD_MALLOC_MODE = -104
+ PI_BAD_SMBUS_CMD = -107
+ PI_NOT_I2C_GPIO = -108
+ PI_BAD_I2C_WLEN = -109
+ PI_BAD_I2C_RLEN = -110
+ PI_BAD_I2C_CMD = -111
+ PI_BAD_I2C_BAUD = -112
+ PI_CHAIN_LOOP_CNT = -113
+ PI_BAD_CHAIN_LOOP = -114
+ PI_CHAIN_COUNTER = -115
+ PI_BAD_CHAIN_CMD = -116
+ PI_BAD_CHAIN_DELAY = -117
+ PI_CHAIN_NESTING = -118
+ PI_CHAIN_TOO_BIG = -119
+ PI_DEPRECATED = -120
. .
frequency: 0-40000
.br
.br
-NOTE: Any waveform started by \fBwave_send_once\fP, \fBwave_send_repeat\fP, \fBwave_tx_start\fP, \fBwave_tx_repeat\fP, or \fBwave_chain\fP
-will be cancelled.
+NOTE: Any waveform started by \fBwave_send_once\fP, \fBwave_send_repeat\fP,
+or \fBwave_chain\fP will be cancelled.
.br
.IP "\fBint wave_create(void)\fP"
.IP "" 4
This function creates a waveform from the data provided by the prior
-calls to the \fBwave_add_*\fP functions. Upon success a positive wave id
-is returned.
+calls to the \fBwave_add_*\fP functions. Upon success a wave id
+greater than or equal to 0 is returned, otherwise PI_EMPTY_WAVEFORM,
+PI_TOO_MANY_CBS, PI_TOO_MANY_OOL, or PI_NO_WAVEFORM_ID.
.br
.IP "\fBint wave_delete(unsigned wave_id)\fP"
.IP "" 4
-This function deletes all created waveforms with ids greater than or
-equal to wave_id.
+This function deletes the waveform with id wave_id.
.br
.br
Returns 0 if OK, otherwise PI_BAD_WAVE_ID.
-.IP "\fBint wave_tx_start(void)\fP"
-.IP "" 4
-This function is deprecated and should no longer be used.
-
-.br
-
-.br
-Use \fBwave_create\fP/\fBwave_send_*\fP instead.
-
-.br
-
-.br
-NOTE: Any hardware PWM started by \fBhardware_PWM\fP will be cancelled.
-
-.IP "\fBint wave_tx_repeat(void)\fP"
-.IP "" 4
-This function is deprecated and should no longer be used.
-
-.br
-
-.br
-Use \fBwave_create\fP/\fBwave_send_*\fP instead.
-
-.br
-
-.br
-NOTE: Any hardware PWM started by \fBhardware_PWM\fP will be cancelled.
-
.IP "\fBint wave_send_once(unsigned wave_id)\fP"
.IP "" 4
This function transmits the waveform with id wave_id. The waveform
.br
The waves to be transmitted are specified by the contents of buf
-which contains an ordered list of wave_ids and optional command
+which contains an ordered list of \fBwave_id\fPs and optional command
codes and related data.
.br
.br
.br
-Returns 0 if OK, otherwise PI_BAD_REPEAT_CNT, PI_BAD_REPEAT_WID,
-PI_BAD_CHAIN_CMD, PI_TOO_MANY_COUNTS, or PI_BAD_WAVE_ID.
+Returns 0 if OK, otherwise PI_CHAIN_NESTING, PI_CHAIN_LOOP_CNT, PI_BAD_CHAIN_LOOP, PI_BAD_CHAIN_CMD, PI_CHAIN_COUNTER,
+PI_BAD_CHAIN_DELAY, PI_CHAIN_TOO_BIG, or PI_BAD_WAVE_ID.
+
+.br
.br
+Each wave is transmitted in the order specified. A wave may
+occur multiple times per chain.
.br
-Each wave is transmitted in the order specified. A wave may only
-occur once per chain. Waves may be transmitted multiple times by
-using the repeat command. The repeat command specifies a wave id
-and a count. The wave id must occur earlier in the chain. All the
-waves between wave id and the repeat command are transmitted count
-times.
.br
+A blocks of waves may be transmitted multiple times by using
+the loop commands. The block is bracketed by loop start and
+end commands. Loops may be nested.
.br
-Repeat commands may not be nested. The minimum repeat count is 2.
-A maximum of 5 repeat commands is supported per chain.
+
+.br
+Delays between waves may be added with the delay command.
.br
.br
.br
-Name Cmd & Data Meaning
+Name Cmd & Data Meaning
+
+.br
+Loop Start 255 0 Identify start of a wave block
+
+.br
+Loop Repeat 255 1 x y loop x + y*256 times
+
+.br
+Delay 255 2 x y delay x + y*256 microseconds
.br
-Repeat 255 wid C0 C1 C2 Repeat from wid count times
.br
-count = C0 + C1*256 + C2*65536
+
+.br
+The code is currently dimensioned to support a chain with roughly
+600 entries and 20 loop counters.
.br
.br
.EX
-The following examples assume that waves with ids 0 to 12 exist.
+#include <stdio.h>
+.br
+#include <pigpiod_if.h>
.br
.br
-// 0 255 0 57 0 0 (repeat 0 57 times)
+#define WAVES 5
.br
-status = wave_chain((char []){0, 255, 0, 57, 0, 0}, 6);
+#define GPIO 4
.br
.br
-// 0 1 255 0 0 2 0 (repeat 0+1 512 times)
+int main(int argc, char *argv[])
+.br
+{
.br
-status = wave_chain((char []){0, 1, 255, 0, 0, 2, 0}, 7);
+ int i, wid[WAVES];
.br
.br
-// 0 1 255 1 0 0 1 (transmit 0, repeat 1 65536 times)
+ if (pigpio_start(0, 0)<0) return -1;
+.br
+
.br
-status = wave_chain((char []){0, 1, 255, 1, 0, 0, 1}, 7);
+ set_mode(GPIO, PI_OUTPUT);
.br
.br
-// 0 1 2 3 255 2 13 0 0 (transmit 0+1, repeat 2+3 13 times)
+ for (i=0; i<WAVES; i++)
+.br
+ {
.br
-status = wave_chain(
+ wave_add_generic(2, (gpioPulse_t[])
.br
- (char []){0, 1, 2, 3, 255, 2, 13, 0, 0}, 9);
+ {{1<<GPIO, 0, 20},
+.br
+ {0, 1<<GPIO, (i+1)*200}});
+.br
+
+.br
+ wid[i] = wave_create();
+.br
+ }
.br
.br
-// The following repeats 5 65793 times, transmits 6,
+ wave_chain((char []) {
+.br
+ wid[4], wid[3], wid[2], // transmit waves 4+3+2
+.br
+ 255, 0, // loop start
+.br
+ wid[0], wid[0], wid[0], // transmit waves 0+0+0
.br
-// repeats 7+8 514 times, transmits 12,
+ 255, 0, // loop start
.br
-// repeats 9+11+10 197121 times.
+ wid[0], wid[1], // transmit waves 0+1
.br
-// 5 255 5 1 1 1 6 7 8 255 7 2 2 0 12 9 11 10 255 9 1 2 3
+ 255, 2, 0x88, 0x13, // delay 5000us
.br
-char chain[] = {
+ 255, 1, 30, 0, // loop end (repeat 30 times)
.br
- 5, 255, 5, 1, 1, 1,
+ 255, 0, // loop start
.br
- 6, 7, 8, 255, 7, 2, 2, 0,
+ wid[2], wid[3], wid[0], // transmit waves 2+3+0
.br
- 12, 9, 11, 10, 255, 9, 1, 2, 3};
+ wid[3], wid[1], wid[2], // transmit waves 3+1+2
+.br
+ 255, 1, 10, 0, // loop end (repeat 10 times)
+.br
+ 255, 1, 5, 0, // loop end (repeat 5 times)
+.br
+ wid[4], wid[4], wid[4], // transmit waves 4+4+4
+.br
+ 255, 2, 0x20, 0x4E, // delay 20000us
+.br
+ wid[0], wid[0], wid[0], // transmit waves 0+0+0
+.br
+
+.br
+ }, 46);
.br
.br
-status = wave_chain(chain, sizeof(chain));
+ while (wave_tx_busy()) time_sleep(0.1);
+.br
+
+.br
+ for (i=0; i<WAVES; i++) wave_delete(wid[i]);
+.br
+
+.br
+ pigpio_stop();
+.br
+}
.br
.EE
For more information, please refer to <http://unlicense.org/>
*/
-/* PIGPIOD_IF_VERSION 16 */
+/* PIGPIOD_IF_VERSION 17 */
#include <stdio.h>
#include <stdlib.h>
#include "pigpio.h"
-#define PIGPIOD_IF_VERSION 16
+#define PIGPIOD_IF_VERSION 17
/*TEXT
wave_get_high_cbs Length of longest waveform so far
wave_get_max_cbs Absolute maximum allowed cbs
-wave_tx_start Creates/transmits a waveform (DEPRECATED)
-wave_tx_repeat Creates/transmits a waveform repeatedly (DEPRECATED)
-
I2C
i2c_open Opens an I2C device
Starts hardware PWM on a gpio at the specified frequency and dutycycle.
Frequencies above 30MHz are unlikely to work.
-NOTE: Any waveform started by [*wave_send_once*], [*wave_send_repeat*], [*wave_tx_start*], [*wave_tx_repeat*], or [*wave_chain*]
-will be cancelled.
+NOTE: Any waveform started by [*wave_send_once*], [*wave_send_repeat*],
+or [*wave_chain*] will be cancelled.
This function is only valid if the pigpio main clock is PCM. The
main clock defaults to PCM but may be overridden when the pigpio
int wave_create(void);
/*D
This function creates a waveform from the data provided by the prior
-calls to the [*wave_add_**] functions. Upon success a positive wave id
-is returned.
+calls to the [*wave_add_**] functions. Upon success a wave id
+greater than or equal to 0 is returned, otherwise PI_EMPTY_WAVEFORM,
+PI_TOO_MANY_CBS, PI_TOO_MANY_OOL, or PI_NO_WAVEFORM_ID.
The data provided by the [*wave_add_**] functions is consumed by this
function.
/*F*/
int wave_delete(unsigned wave_id);
/*D
-This function deletes all created waveforms with ids greater than or
-equal to wave_id.
+This function deletes the waveform with id wave_id.
. .
wave_id: >=0, as returned by [*wave_create*].
Returns 0 if OK, otherwise PI_BAD_WAVE_ID.
D*/
-/*F*/
-int wave_tx_start(void);
-/*D
-This function is deprecated and should no longer be used.
-
-Use [*wave_create*]/[*wave_send_**] instead.
-
-NOTE: Any hardware PWM started by [*hardware_PWM*] will be cancelled.
-D*/
-
-/*F*/
-int wave_tx_repeat(void);
-/*D
-This function is deprecated and should no longer be used.
-
-Use [*wave_create*]/[*wave_send_**] instead.
-
-NOTE: Any hardware PWM started by [*hardware_PWM*] will be cancelled.
-D*/
-
/*F*/
int wave_send_once(unsigned wave_id);
/*D
NOTE: Any hardware PWM started by [*hardware_PWM*] will be cancelled.
The waves to be transmitted are specified by the contents of buf
-which contains an ordered list of wave_ids and optional command
+which contains an ordered list of [*wave_id*]s and optional command
codes and related data.
. .
bufSize: the number of bytes in buf
. .
-Returns 0 if OK, otherwise PI_BAD_REPEAT_CNT, PI_BAD_REPEAT_WID,
-PI_BAD_CHAIN_CMD, PI_TOO_MANY_COUNTS, or PI_BAD_WAVE_ID.
-
-Each wave is transmitted in the order specified. A wave may only
-occur once per chain. Waves may be transmitted multiple times by
-using the repeat command. The repeat command specifies a wave id
-and a count. The wave id must occur earlier in the chain. All the
-waves between wave id and the repeat command are transmitted count
-times.
+Returns 0 if OK, otherwise PI_CHAIN_NESTING, PI_CHAIN_LOOP_CNT, PI_BAD_CHAIN_LOOP, PI_BAD_CHAIN_CMD, PI_CHAIN_COUNTER,
+PI_BAD_CHAIN_DELAY, PI_CHAIN_TOO_BIG, or PI_BAD_WAVE_ID.
-Repeat commands may not be nested. The minimum repeat count is 2.
-A maximum of 5 repeat commands is supported per chain.
+Each wave is transmitted in the order specified. A wave may
+occur multiple times per chain.
-The following command codes are supported:
+A blocks of waves may be transmitted multiple times by using
+the loop commands. The block is bracketed by loop start and
+end commands. Loops may be nested.
-Name @ Cmd & Data @ Meaning
-Repeat @ 255 wid C0 C1 C2 @ Repeat from wid count times
-count = C0 + C1*256 + C2*65536
+Delays between waves may be added with the delay command.
-...
-The following examples assume that waves with ids 0 to 12 exist.
-
-// 0 255 0 57 0 0 (repeat 0 57 times)
-status = wave_chain((char []){0, 255, 0, 57, 0, 0}, 6);
+The following command codes are supported:
-// 0 1 255 0 0 2 0 (repeat 0+1 512 times)
-status = wave_chain((char []){0, 1, 255, 0, 0, 2, 0}, 7);
+Name @ Cmd & Data @ Meaning
+Loop Start @ 255 0 @ Identify start of a wave block
+Loop Repeat @ 255 1 x y @ loop x + y*256 times
+Delay @ 255 2 x y @ delay x + y*256 microseconds
-// 0 1 255 1 0 0 1 (transmit 0, repeat 1 65536 times)
-status = wave_chain((char []){0, 1, 255, 1, 0, 0, 1}, 7);
+The code is currently dimensioned to support a chain with roughly
+600 entries and 20 loop counters.
-// 0 1 2 3 255 2 13 0 0 (transmit 0+1, repeat 2+3 13 times)
-status = wave_chain(
- (char []){0, 1, 2, 3, 255, 2, 13, 0, 0}, 9);
+...
+#include <stdio.h>
+#include <pigpiod_if.h>
-// The following repeats 5 65793 times, transmits 6,
-// repeats 7+8 514 times, transmits 12,
-// repeats 9+11+10 197121 times.
-// 5 255 5 1 1 1 6 7 8 255 7 2 2 0 12 9 11 10 255 9 1 2 3
-char chain[] = {
- 5, 255, 5, 1, 1, 1,
- 6, 7, 8, 255, 7, 2, 2, 0,
- 12, 9, 11, 10, 255, 9, 1, 2, 3};
+#define WAVES 5
+#define GPIO 4
-status = wave_chain(chain, sizeof(chain));
+int main(int argc, char *argv[])
+{
+ int i, wid[WAVES];
+
+ if (pigpio_start(0, 0)<0) return -1;
+
+ set_mode(GPIO, PI_OUTPUT);
+
+ for (i=0; i<WAVES; i++)
+ {
+ wave_add_generic(2, (gpioPulse_t[])
+ {{1<<GPIO, 0, 20},
+ {0, 1<<GPIO, (i+1)*200}});
+
+ wid[i] = wave_create();
+ }
+
+ wave_chain((char []) {
+ wid[4], wid[3], wid[2], // transmit waves 4+3+2
+ 255, 0, // loop start
+ wid[0], wid[0], wid[0], // transmit waves 0+0+0
+ 255, 0, // loop start
+ wid[0], wid[1], // transmit waves 0+1
+ 255, 2, 0x88, 0x13, // delay 5000us
+ 255, 1, 30, 0, // loop end (repeat 30 times)
+ 255, 0, // loop start
+ wid[2], wid[3], wid[0], // transmit waves 2+3+0
+ wid[3], wid[1], wid[2], // transmit waves 3+1+2
+ 255, 1, 10, 0, // loop end (repeat 10 times)
+ 255, 1, 5, 0, // loop end (repeat 5 times)
+ wid[4], wid[4], wid[4], // transmit waves 4+4+4
+ 255, 2, 0x20, 0x4E, // delay 20000us
+ wid[0], wid[0], wid[0], // transmit waves 0+0+0
+
+ }, 46);
+
+ while (wave_tx_busy()) time_sleep(0.1);
+
+ for (i=0; i<WAVES; i++) wave_delete(wid[i]);
+
+ pigpio_stop();
+}
...
D*/
are unlikely to work.
.br
-NOTE: Any waveform started by \fBWVGO\fP, \fBWVGOR\fP, \fBWVTX\fP,
-\fBWVTXR\fP, or \fBWVCHA\fP will be cancelled.
+NOTE: Any waveform started by \fBWVTX\fP, \fBWVTXR\fP, or \fBWVCHA\fP
+will be cancelled.
.br
This function is only valid if the pigpio main clock is PCM. The
.br
Each wave is transmitted in the order specified. A wave may
-only occur once per chain. Waves may be transmitted multiple
-times by using the repeat command. The repeat command
-specifies a wave id and a count. The wave id must occur
-earlier in the chain. All the waves between wave id and the
-repeat command are transmitted count times.
+occur multiple times per chain.
.br
-Repeat commands may not be nested. The minimum repeat
-count is 2. A maximum of 5 repeat commands is supported
-per chain.
+A blocks of waves may be transmitted multiple times by using
+the loop commands. The block is bracketed by loop start and
+end commands. Loops may be nested.
+
+.br
+Delays between waves may be added with the delay command.
.br
The following command codes are supported:
.br
.EX
-Name Cmd & Data Meaning
-Repeat 255 wid C0 C1 C2 Repeat from wid count times
+Name Cmd & Data Meaning
+Loop Start 255 0 Identify start of a wave block
+Loop Repeat 255 1 x y loop x + y*256 times
+Delay 255 2 x y delay x + y*256 microseconds
.EE
-count = C0 + C1*256 + C2*65536
+
+.br
+The code is currently dimensioned to support a chain with roughly
+600 entries and 20 loop counters.
.br
.br
.EX
-The following examples assume that waves with ids 0 to 12 exist.
+#!/bin/bash
.br
.br
-# 0 255 0 57 0 0 (repeat 0 57 times)
+GPIO=4
.br
-$ pigs wvcha 0 255 0 57 0 0
+WAVES=5
.br
.br
-# 0 1 255 0 0 2 0 (repeat 0+1 512 times)
-.br
-$ pigs wvcha 0 1 255 0 0 2 0
+pigs m $GPIO w
.br
.br
-# 0 1 255 1 0 0 1 (transmit 0, repeat 1 65536 times)
+for ((i=0; i<$WAVES; i++))
+.br
+do
+.br
+ pigs wvag $((1<<GPIO)) 0 20 0 $((1<<GPIO)) $(((i+1)*200))
+.br
+ w[i]=$(pigs wvcre)
.br
-$ pigs wvcha 0 1 255 1 0 0 1
+done
.br
.br
-# 0 1 2 3 255 2 13 0 0 (transmit 0+1, repeat 2+3 13 times)
+# transmit waves 4+3+2
+.br
+# loop start
+.br
+# transmit waves 0+0+0
+.br
+# loop start
+.br
+# transmit waves 0+1
+.br
+# delay 5000us
+.br
+# loop end (repeat 30 times)
+.br
+# loop start
+.br
+# transmit waves 2+3+0
.br
-$ pigs wvcha 0 1 2 3 255 2 13 0 0
+# transmit waves 3+1+2
+.br
+# loop end (repeat 10 times)
+.br
+# loop end (repeat 5 times)
+.br
+# transmit waves 4+4+4
+.br
+# delay 20000us
+.br
+# transmit waves 0+0+0
.br
.br
-# The following repeats 5 65793 times, transmits 6,
+pigs wvcha \\
+.br
+ ${w[4]} ${w[3]} ${w[2]} \\
+.br
+ 255 0 \\
+.br
+ ${w[0]} ${w[0]} ${w[0]} \\
+.br
+ 255 0 \\
+.br
+ ${w[0]} ${w[1]} \\
+.br
+ 255 2 0x88 0x13 \\
+.br
+ 255 1 30 0 \\
+.br
+ 255 0 \\
+.br
+ ${w[2]} ${w[3]} ${w[0]} \\
+.br
+ ${w[3]} ${w[1]} ${w[2]} \\
+.br
+ 255 1 10 0 \\
.br
-# repeats 7+8 514 times, transmits 12,
+ 255 1 5 0 \\
.br
-# repeats 9+11+10 197121 times.
+ ${w[4]} ${w[4]} ${w[4]} \\
.br
-# 5 255 5 1 1 1 6 7 8 255 7 2 2 0 12 9 11 10 255 9 1 2 3
+ 255 2 0x20 0x4E \\
.br
-$ pigs wvcha 5 255 5 1 1 1 6 7 8 255 7 2 2 0 12 9 11 10 255 9 1 2 3
+ ${w[0]} ${w[0]} ${w[0]}
+.br
+
+.br
+while [[ $(pigs wvbsy) -eq 1 ]]; do sleep 0.1; done
+.br
+
+.br
+for ((i=0; i<$WAVES; i++)); do echo ${w[i]}; pigs wvdel ${w[i]}; done
.br
.EE
.IP "" 4
.br
-This command deletes all waveforms with ids greater than or equal to \fBwid\fP.
+This command deletes the waveform with id \fBwid\fP.
.br
Upon success nothing is returned. On error a negative status code
.br
-.IP "\fBWVGO \fP - Transmit waveform once (DEPRECATED)"
-.IP "" 4
-
-.br
-This command transmits the current waveform. The waveform is sent once.
-
-.br
-NOTE: Any hardware PWM started by \fBHP\fP will be cancelled.
-
-.br
-Upon success the number of DMA control blocks in the waveform is returned.
-On error a negative status code will be returned.
-
-.br
-
-.IP "\fBWVGOR \fP - Transmit waveform repeatedly (DEPRECATED)"
-.IP "" 4
-
-.br
-This command transmits the current waveform. The waveform is sent repeatedly.
-
-.br
-NOTE: Any hardware PWM started by \fBHP\fP will be cancelled.
-
-.br
-Upon success the number of DMA control blocks in the waveform is returned.
-On error a negative status code will be returned.
-
-.br
-
.IP "\fBWVHLT \fP - Stop waveform"
.IP "" 4
.br
.EX
-time (pigs procr 0 10000000; while a=$(pigs procp 0); [[ ${a::1} -eq 2 ]];\
+time (pigs procr 0 10000000; while a=$(pigs procp 0); [[ ${a::1} -eq 2 ]];\\
.br
do sleep 0.2; done)
.br
.br
.EX
-time (pigs procr 0 10000000; while a=$(pigs procp 0); [[ ${a::1} -eq 2 ]];\
+time (pigs procr 0 10000000; while a=$(pigs procp 0); [[ ${a::1} -eq 2 ]];\\
.br
do sleep 0.2; done)
.br
from distutils.core import setup
setup(name='pigpio',
- version='1.19',
+ version='1.20',
author='joan',
author_email='joan@abyz.co.uk',
maintainer='joan',
{0, 1<<GPIO, 100000},
};
- int e, oc, c;
+ int e, oc, c, wid;
char text[2048];
e = gpioWaveAddGeneric(4, wf);
CHECK(5, 2, e, 4, 0, "pulse, wave add generic");
- e = gpioWaveTxStart(PI_WAVE_MODE_REPEAT);
+ wid = gpioWaveCreate();
+ e = gpioWaveTxSend(wid, PI_WAVE_MODE_REPEAT);
CHECK(5, 3, e, 9, 0, "wave tx repeat");
oc = t5_count;
e = gpioWaveAddSerial(GPIO, BAUD, 8, 2, 5000000, strlen(TEXT), TEXT);
CHECK(5, 7, e, 3405, 0, "wave clear, wave add serial");
- e = gpioWaveTxStart(PI_WAVE_MODE_ONE_SHOT);
+ wid = gpioWaveCreate();
+ e = gpioWaveTxSend(wid, PI_WAVE_MODE_ONE_SHOT);
CHECK(5, 8, e, 6811, 0, "wave tx start");
CHECK(5, 9, 0, 0, 0, "NOT APPLICABLE");
e = pi.wave_add_generic(wf)
CHECK(5, 2, e, 4, 0, "pulse, wave add generic")
- e = pi.wave_tx_repeat()
- CHECK(5, 3, e, 9, 0, "wave tx repeat")
+ wid = pi.wave_create()
+ e = pi.wave_send_repeat(wid)
+ CHECK(5, 3, e, 9, 0, "wave send repeat")
oc = t5_count
time.sleep(5)
e = pi.wave_add_serial(GPIO, BAUD, TEXT, 5000000)
CHECK(5, 7, e, 3405, 0, "wave clear, wave add serial")
- e = pi.wave_tx_start()
- CHECK(5, 8, e, 6811, 0, "wave tx start")
+ wid = pi.wave_create()
+ e = pi.wave_send_once(wid)
+ CHECK(5, 8, e, 6811, 0, "wave send once")
oc = t5_count
time.sleep(3)
{0, 1<<GPIO, 100000},
};
- int e, oc, c;
+ int e, oc, c, wid;
char text[2048];
e = wave_add_generic(4, wf);
CHECK(5, 2, e, 4, 0, "pulse, wave add generic");
- e = wave_tx_repeat();
+ wid = wave_create();
+ e = wave_send_repeat(wid);
CHECK(5, 3, e, 9, 0, "wave tx repeat");
oc = t5_count;
e = wave_add_serial(GPIO, BAUD, 8, 2, 5000000, strlen(TEXT), TEXT);
CHECK(5, 7, e, 3405, 0, "wave clear, wave add serial");
- e = wave_tx_start();
+ wid = wave_create();
+ e = wave_send_once(wid);
CHECK(5, 8, e, 6811, 0, "wave tx start");
oc = t5_count;
if [[ $s = 95 ]]; then echo "SLR-c ok"; else echo "SLR-c fail ($s)"; fi
s=$(pigs m $GPIO w)
if [[ $s = "" ]]; then echo "SLR-d ok"; else echo "SLR-d fail ($s)"; fi
-s=$(pigs wvgo)
+w=$(pigs wvcre)
+if [[ $w -ge 0 ]]; then echo "WVCRE ok"; else echo "WVCRE fail ($s)"; fi
+s=$(pigs wvtx $w)
if [[ $s = 191 ]]; then echo "SLR-e ok"; else echo "SLR-e fail ($s)"; fi
sleep 0.2
s=$(pigs slr $GPIO 100)
if [[ $s = 309 ]]; then echo "WVAS ok"; else echo "WVAS fail ($s)"; fi
s=$(pigs wvag 16 0 5000000 0 16 5000000)
if [[ $s = 310 ]]; then echo "WVAG ok"; else echo "WVAG fail ($s)"; fi
-s=$(pigs wvgo)
-if [[ $s = 621 ]]; then echo "WVGO ok"; else echo "WVGO fail ($s)"; fi
+w=$(pigs wvcre)
+if [[ $w -ge 0 ]]; then echo "WVCRE ok"; else echo "WVCRE fail ($s)"; fi
+s=$(pigs wvtx $w)
+if [[ $s = 621 ]]; then echo "WVTX ok"; else echo "WVTX fail ($s)"; fi
s=$(pigs wvbsy)
if [[ $s = 1 ]]; then echo "WVBSY-a ok"; else echo "WVBSY-a fail ($s)"; fi
sleep 1
if [[ $s = "" ]]; then echo "WVHLT ok"; else echo "WVHLT fail ($s)"; fi
s=$(pigs wvbsy)
if [[ $s = 0 ]]; then echo "WVBSY-c ok"; else echo "WVBSY-c fail ($s)"; fi
-s=$(pigs wvgor)
-if [[ $s = 621 ]]; then echo "WVGOR ok"; else echo "WVGOR fail ($s)"; fi
+s=$(pigs wvtxr $w)
+if [[ $s = 621 ]]; then echo "WVTXR ok"; else echo "WVTXR fail ($s)"; fi
s=$(pigs wvbsy)
if [[ $s = 1 ]]; then echo "WVBSY-d ok"; else echo "WVBSY-d fail ($s)"; fi
s=$(pigs wvhlt)
echo "m $GPIO w" >/dev/pigpio
read -t 1 s </dev/pigout
if [[ $s = 0 ]]; then echo "SLR-d ok"; else echo "SLR-d fail ($s)"; fi
-echo "wvgo" >/dev/pigpio
+echo "wvcre" >/dev/pigpio
+read -t 1 w </dev/pigout
+if [[ $w -ge 0 ]]; then echo "WVCRE ok"; else echo "WVCRE fail ($w)"; fi
+echo "wvtx $w" >/dev/pigpio
read -t 1 s </dev/pigout
if [[ $s = 191 ]]; then echo "SLR-e ok"; else echo "SLR-e fail ($s)"; fi
sleep 0.2
echo "wvag 16 0 5000000 0 16 5000000" >/dev/pigpio
read -t 1 s </dev/pigout
if [[ $s = 216 ]]; then echo "WVAG ok"; else echo "WVAG fail ($s)"; fi
-echo "wvgo" >/dev/pigpio
+echo "wvcre" >/dev/pigpio
+read -t 1 w </dev/pigout
+if [[ $w -ge 0 ]]; then echo "WVCRE ok"; else echo "WVCRE fail ($s)"; fi
+echo "wvtx $w" >/dev/pigpio
read -t 1 s </dev/pigout
-if [[ $s = 433 ]]; then echo "WVGO ok"; else echo "WVGO fail ($s)"; fi
+if [[ $s = 433 ]]; then echo "WVTX ok"; else echo "WVTX fail ($s)"; fi
echo "wvbsy" >/dev/pigpio
read -t 1 s </dev/pigout
if [[ $s = 1 ]]; then echo "WVBSY-a ok"; else echo "WVBSY-a fail ($s)"; fi
echo "wvbsy" >/dev/pigpio
read -t 1 s </dev/pigout
if [[ $s = 0 ]]; then echo "WVBSY-c ok"; else echo "WVBSY-c fail ($s)"; fi
-echo "wvgor" >/dev/pigpio
+echo "wvtxr $w" >/dev/pigpio
read -t 1 s </dev/pigout
-if [[ $s = 433 ]]; then echo "WVGOR ok"; else echo "WVGOR fail ($s)"; fi
+if [[ $s = 433 ]]; then echo "WVTXR ok"; else echo "WVTXR fail ($s)"; fi
echo "wvbsy" >/dev/pigpio
read -t 1 s </dev/pigout
if [[ $s = 1 ]]; then echo "WVBSY-d ok"; else echo "WVBSY-d fail ($s)"; fi